From 056d6ebbd9e03f97db65ab5e23c30e9b646a5b31 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 28 Oct 2019 16:07:01 +0800 Subject: [PATCH] improve interface design for gsession.Storage --- os/gsession/gsession_manager.go | 4 +++- os/gsession/gsession_session.go | 8 ++++---- os/gsession/gsession_storage.go | 24 +++++++++++++++++++----- os/gsession/gsession_storage_file.go | 25 +++++++++++++++++++------ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/os/gsession/gsession_manager.go b/os/gsession/gsession_manager.go index 1be4f60ce..4891eb770 100644 --- a/os/gsession/gsession_manager.go +++ b/os/gsession/gsession_manager.go @@ -39,9 +39,11 @@ func (m *Manager) New(sessionId ...string) *Session { id = sessionId[0] } // NOTE: - // We CANNOT creates and stores it directly to manager + // We CANNOT creates and stores session directly to manager // as it might be a fake and invalid session id // which would consumes your memory as much as possible. + // + // We here create a temporary tiny session struct. return &Session{ id: id, manager: m, diff --git a/os/gsession/gsession_session.go b/os/gsession/gsession_session.go index d621a7f93..e2cb32b38 100644 --- a/os/gsession/gsession_session.go +++ b/os/gsession/gsession_session.go @@ -54,7 +54,7 @@ func (s *Session) init() { // Set sets key-value pair to this session. func (s *Session) Set(key string, value interface{}) error { s.init() - if err := s.manager.storage.Set(s.id, key, value); err != nil { + if err := s.manager.storage.Set(s.id, key, value, s.manager.ttl); err != nil { if err == ErrorDisabled { s.data.Set(key, value) } else { @@ -68,7 +68,7 @@ func (s *Session) Set(key string, value interface{}) error { // Sets batch sets the session using map. func (s *Session) Sets(data map[string]interface{}) error { s.init() - if err := s.manager.storage.SetMap(s.id, data); err != nil { + if err := s.manager.storage.SetMap(s.id, data, s.manager.ttl); err != nil { if err == ErrorDisabled { s.data.Sets(data) } else { @@ -173,12 +173,12 @@ func (s *Session) Close() { if s.manager.storage != nil { if s.dirty.Cas(true, false) { s.data.RLockFunc(func(m map[string]interface{}) { - if err := s.manager.storage.SetSession(s.id, m); err != nil { + if err := s.manager.storage.SetSession(s.id, m, s.manager.ttl); err != nil { panic(err) } }) } else { - if err := s.manager.storage.UpdateTTL(s.id); err != nil { + if err := s.manager.storage.UpdateTTL(s.id, s.manager.ttl); err != nil { panic(err) } } diff --git a/os/gsession/gsession_storage.go b/os/gsession/gsession_storage.go index 11a538cd7..7eee2c221 100644 --- a/os/gsession/gsession_storage.go +++ b/os/gsession/gsession_storage.go @@ -9,31 +9,45 @@ package gsession import "time" type Storage interface { + // New creates a custom session id. + // This function can be used for custom session creation. + New(ttl time.Duration) (id string) + // Get retrieves session value with given key. // It returns nil if the key does not exist in the session. Get(id string, key string) interface{} + // GetMap retrieves all key-value pairs as map from storage. GetMap(id string) map[string]interface{} + // GetSize retrieves the size of key-value pairs from storage. GetSize(id string) int // Set sets key-value session pair to the storage. - Set(id string, key string, value interface{}) error + // The parameter specifies the TTL for the session id (not for the key-value pair). + Set(id string, key string, value interface{}, ttl time.Duration) error + // SetMap batch sets key-value session pairs with map to the storage. - SetMap(id string, data map[string]interface{}) error + // The parameter specifies the TTL for the session id(not for the key-value pair). + SetMap(id string, data map[string]interface{}, ttl time.Duration) error // Remove deletes key with its value from storage. Remove(id string, key string) error + // RemoveAll deletes all key-value pairs from storage. RemoveAll(id string) error - // GetSession returns the session data map for given session id. + // GetSession returns the session data as map for given session id. // The parameter specifies the TTL for this session. // It returns nil if the TTL is exceeded. GetSession(id string, ttl time.Duration) map[string]interface{} + // SetSession updates the data map for specified session id. - SetSession(id string, data map[string]interface{}) error + // This function is called ever after session, which is changed dirty, is closed. + // This copy all session data map from memory to storage. + SetSession(id string, data map[string]interface{}, ttl time.Duration) error // UpdateTTL updates the TTL for specified session id. - UpdateTTL(id string) error + // This function is called ever after session, which is not dirty, is closed. + UpdateTTL(id string, ttl time.Duration) error } diff --git a/os/gsession/gsession_storage_file.go b/os/gsession/gsession_storage_file.go index 0f4b810e0..ad58686d0 100644 --- a/os/gsession/gsession_storage_file.go +++ b/os/gsession/gsession_storage_file.go @@ -101,6 +101,12 @@ func (s *StorageFile) sessionFilePath(id string) string { return gfile.Join(s.path, id) } +// New creates a session id. +// This function can be used for custom session creation. +func (s *StorageFile) New(ttl time.Duration) (id string) { + return "" +} + // Get retrieves session value with given key. // It returns nil if the key does not exist in the session. func (s *StorageFile) Get(id string, key string) interface{} { @@ -118,12 +124,14 @@ func (s *StorageFile) GetSize(id string) int { } // Set sets key-value session pair to the storage. -func (s *StorageFile) Set(id string, key string, value interface{}) error { +// The parameter specifies the TTL for the session id (not for the key-value pair). +func (s *StorageFile) Set(id string, key string, value interface{}, ttl time.Duration) error { return ErrorDisabled } // SetMap batch sets key-value session pairs with map to the storage. -func (s *StorageFile) SetMap(id string, data map[string]interface{}) error { +// The parameter specifies the TTL for the session id(not for the key-value pair). +func (s *StorageFile) SetMap(id string, data map[string]interface{}, ttl time.Duration) error { return ErrorDisabled } @@ -137,7 +145,9 @@ func (s *StorageFile) RemoveAll(id string) error { return ErrorDisabled } -// GetSession return the session data for given session id. +// GetSession returns the session data as map for given session id. +// The parameter specifies the TTL for this session. +// It returns nil if the TTL is exceeded. func (s *StorageFile) GetSession(id string, ttl time.Duration) map[string]interface{} { path := s.sessionFilePath(id) data := gfile.GetBytes(path) @@ -164,8 +174,10 @@ func (s *StorageFile) GetSession(id string, ttl time.Duration) map[string]interf return nil } -// SetSession updates the content for session id. -func (s *StorageFile) SetSession(id string, data map[string]interface{}) error { +// SetSession updates the data map for specified session id. +// This function is called ever after session, which is changed dirty, is closed. +// This copy all session data map from memory to storage. +func (s *StorageFile) SetSession(id string, data map[string]interface{}, ttl time.Duration) error { path := s.sessionFilePath(id) content, err := json.Marshal(data) if err != nil { @@ -192,8 +204,9 @@ func (s *StorageFile) SetSession(id string, data map[string]interface{}) error { } // UpdateTTL updates the TTL for specified session id. +// This function is called ever after session, which is not dirty, is closed. // It just adds the session id to the async handling queue. -func (s *StorageFile) UpdateTTL(id string) error { +func (s *StorageFile) UpdateTTL(id string, ttl time.Duration) error { s.updatingIdSet.Add(id) return nil }