/
uzer_007
/
Rixea
Обзор
Документация
Войти
/
uzer_007
/
Rixea
Код
Запросы
0
Задачи
Вики
Пакеты
5
Релизы
2
CI/CD
Аналитика
Безопасность
master
modules/session/virtual.go
184 строки
4 KB
uzer_007
feat: первая версия Rixea
02 авг 2026, 22:16
02 авг 2026, 22:16
d4f7504
Код
Авторство
О чём код?
// Copyright 2026 Uzer_007. All rights reserved. // SPDX-License-Identifier: MIT package session import ( "fmt" "sync" "gitverse.ru/uzer_007/Rixea/modules/json" ) // VirtualSessionProvider represents a shadowed session provider implementation. type VirtualSessionProvider struct { lock sync.RWMutex provider Provider } // Init initializes the cookie session provider with the given config. func (o *VirtualSessionProvider) Init(gcLifetime int64, config string) error { var opts Options if err := json.Unmarshal([]byte(config), &opts); err != nil { return err } switch opts.Provider { case "memory": o.provider = &MemProvider{} case "file": o.provider = &FileProvider{} case "redis": o.provider = &RedisProvider{} case "db": o.provider = &DBProvider{} default: return fmt.Errorf("VirtualSessionProvider: Unknown Provider: %s", opts.Provider) } return o.provider.Init(gcLifetime, opts.ProviderConfig) } // Read returns raw session store by session ID. func (o *VirtualSessionProvider) Read(sid string) (RawStore, error) { o.lock.RLock() defer o.lock.RUnlock() if exist, err := o.provider.Exist(sid); err == nil && exist { return o.provider.Read(sid) } else if err != nil { return nil, fmt.Errorf("check if '%s' exist failed: %w", sid, err) } kv := make(map[any]any) return NewVirtualStore(o, sid, kv), nil } // Exist returns true if session with given ID exists. func (o *VirtualSessionProvider) Exist(sid string) (bool, error) { return true, nil } // Destroy deletes a session by session ID. func (o *VirtualSessionProvider) Destroy(sid string) error { o.lock.Lock() defer o.lock.Unlock() return o.provider.Destroy(sid) } // Regenerate regenerates a session store from old session ID to new one. func (o *VirtualSessionProvider) Regenerate(oldsid, sid string) (RawStore, error) { o.lock.Lock() defer o.lock.Unlock() return o.provider.Regenerate(oldsid, sid) } // Count counts and returns number of sessions. func (o *VirtualSessionProvider) Count() (int, error) { o.lock.RLock() defer o.lock.RUnlock() return o.provider.Count() } // GC calls GC to clean expired sessions. func (o *VirtualSessionProvider) GC() { o.provider.GC() } func init() { Register("VirtualSession", &VirtualSessionProvider{}) } // VirtualStore represents a virtual session store implementation. type VirtualStore struct { p *VirtualSessionProvider sid string lock sync.RWMutex data map[any]any released bool } // NewVirtualStore creates and returns a virtual session store. func NewVirtualStore(p *VirtualSessionProvider, sid string, kv map[any]any) *VirtualStore { return &VirtualStore{ p: p, sid: sid, data: kv, } } // Set sets value to given key in session. func (s *VirtualStore) Set(key, val any) error { s.lock.Lock() defer s.lock.Unlock() s.data[key] = val return nil } // Get gets value by given key in session. func (s *VirtualStore) Get(key any) any { s.lock.RLock() defer s.lock.RUnlock() return s.data[key] } // Delete delete a key from session. func (s *VirtualStore) Delete(key any) error { s.lock.Lock() defer s.lock.Unlock() delete(s.data, key) return nil } // ID returns current session ID. func (s *VirtualStore) ID() string { return s.sid } // Release releases resource and save data to provider. func (s *VirtualStore) Release() error { s.lock.Lock() defer s.lock.Unlock() // Now need to lock the provider s.p.lock.Lock() defer s.p.lock.Unlock() if len(s.data) > 0 { // Now ensure that we don't exist! realProvider := s.p.provider if !s.released { if exist, err := realProvider.Exist(s.sid); err == nil && exist { // This is an error! return fmt.Errorf("new sid '%s' already exists", s.sid) } else if err != nil { return fmt.Errorf("check if '%s' exist failed: %w", s.sid, err) } } realStore, err := realProvider.Read(s.sid) if err != nil { return err } if err := realStore.Flush(); err != nil { return err } for key, value := range s.data { if err := realStore.Set(key, value); err != nil { return err } } err = realStore.Release() if err == nil { s.released = true } return err } return nil } // Flush deletes all session data. func (s *VirtualStore) Flush() error { s.lock.Lock() defer s.lock.Unlock() s.data = make(map[any]any) return nil }