database.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package sessions
  2. import (
  3. "sync"
  4. "time"
  5. "github.com/kataras/iris/core/errors"
  6. "github.com/kataras/iris/core/memstore"
  7. )
  8. // ErrNotImplemented is returned when a particular feature is not yet implemented yet.
  9. // It can be matched directly, i.e: `isNotImplementedError := sessions.ErrNotImplemented.Equal(err)`.
  10. var ErrNotImplemented = errors.New("not implemented yet")
  11. // Database is the interface which all session databases should implement
  12. // By design it doesn't support any type of cookie session like other frameworks.
  13. // I want to protect you, believe me.
  14. // The scope of the database is to store somewhere the sessions in order to
  15. // keep them after restarting the server, nothing more.
  16. //
  17. // Synchronization are made automatically, you can register one using `UseDatabase`.
  18. //
  19. // Look the `sessiondb` folder for databases implementations.
  20. type Database interface {
  21. // Acquire receives a session's lifetime from the database,
  22. // if the return value is LifeTime{} then the session manager sets the life time based on the expiration duration lives in configuration.
  23. Acquire(sid string, expires time.Duration) LifeTime
  24. // OnUpdateExpiration should re-set the expiration (ttl) of the session entry inside the database,
  25. // it is fired on `ShiftExpiration` and `UpdateExpiration`.
  26. // If the database does not support change of ttl then the session entry will be cloned to another one
  27. // and the old one will be removed, it depends on the chosen database storage.
  28. //
  29. // Check of error is required, if error returned then the rest session's keys are not proceed.
  30. //
  31. // If a database does not support this feature then an `ErrNotImplemented` will be returned instead.
  32. OnUpdateExpiration(sid string, newExpires time.Duration) error
  33. // Set sets a key value of a specific session.
  34. // The "immutable" input argument depends on the store, it may not implement it at all.
  35. Set(sid string, lifetime LifeTime, key string, value interface{}, immutable bool)
  36. // Get retrieves a session value based on the key.
  37. Get(sid string, key string) interface{}
  38. // Visit loops through all session keys and values.
  39. Visit(sid string, cb func(key string, value interface{}))
  40. // Len returns the length of the session's entries (keys).
  41. Len(sid string) int
  42. // Delete removes a session key value based on its key.
  43. Delete(sid string, key string) (deleted bool)
  44. // Clear removes all session key values but it keeps the session entry.
  45. Clear(sid string)
  46. // Release destroys the session, it clears and removes the session entry,
  47. // session manager will create a new session ID on the next request after this call.
  48. Release(sid string)
  49. }
  50. type mem struct {
  51. values map[string]*memstore.Store
  52. mu sync.RWMutex
  53. }
  54. var _ Database = (*mem)(nil)
  55. func newMemDB() Database { return &mem{values: make(map[string]*memstore.Store)} }
  56. func (s *mem) Acquire(sid string, expires time.Duration) LifeTime {
  57. s.mu.Lock()
  58. s.values[sid] = new(memstore.Store)
  59. s.mu.Unlock()
  60. return LifeTime{}
  61. }
  62. // Do nothing, the `LifeTime` of the Session will be managed by the callers automatically on memory-based storage.
  63. func (s *mem) OnUpdateExpiration(string, time.Duration) error { return nil }
  64. // immutable depends on the store, it may not implement it at all.
  65. func (s *mem) Set(sid string, lifetime LifeTime, key string, value interface{}, immutable bool) {
  66. s.mu.RLock()
  67. s.values[sid].Save(key, value, immutable)
  68. s.mu.RUnlock()
  69. }
  70. func (s *mem) Get(sid string, key string) interface{} {
  71. s.mu.RLock()
  72. v := s.values[sid].Get(key)
  73. s.mu.RUnlock()
  74. return v
  75. }
  76. func (s *mem) Visit(sid string, cb func(key string, value interface{})) {
  77. s.values[sid].Visit(cb)
  78. }
  79. func (s *mem) Len(sid string) int {
  80. s.mu.RLock()
  81. n := s.values[sid].Len()
  82. s.mu.RUnlock()
  83. return n
  84. }
  85. func (s *mem) Delete(sid string, key string) (deleted bool) {
  86. s.mu.RLock()
  87. deleted = s.values[sid].Remove(key)
  88. s.mu.RUnlock()
  89. return
  90. }
  91. func (s *mem) Clear(sid string) {
  92. s.mu.Lock()
  93. s.values[sid].Reset()
  94. s.mu.Unlock()
  95. }
  96. func (s *mem) Release(sid string) {
  97. s.mu.Lock()
  98. delete(s.values, sid)
  99. s.mu.Unlock()
  100. }