package session import ( "context" "time" "github.com/go-redis/redis/v8" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" "repositories.action2quare.com/ayo/gocommon" ) type Provider interface { Update(string, *Authorization) error Delete(string) error Query(string) (*Authorization, error) } type provider_redis struct { redisClient *redis.Client updateChannel string deleteChannel string ttl time.Duration ctx context.Context } type provider_mongo struct { mongoClient gocommon.MongoClient } func NewProviderWithMongo(ctx context.Context, mongoUrl string, dbname string, ttl time.Duration) (Provider, error) { mc, err := gocommon.NewMongoClient(ctx, mongoUrl, dbname) if err != nil { return nil, err } if err = mc.MakeUniqueIndices(session_collection_name, map[string]bson.D{ "key": {{Key: "key", Value: 1}}, }); err != nil { return nil, err } if err := mc.MakeExpireIndex(session_collection_name, int32(ttl.Seconds())); err != nil { return nil, err } return &provider_mongo{ mongoClient: mc, }, nil } func NewProviderWithRedis(ctx context.Context, redisUrl string, ttl time.Duration) (Provider, error) { redisClient, err := gocommon.NewRedisClient(redisUrl) if err != nil { return nil, err } return &provider_redis{ redisClient: redisClient, updateChannel: communication_channel_name_prefix + "_u", deleteChannel: communication_channel_name_prefix + "_d", ttl: ttl, ctx: ctx, }, nil } func (p *provider_redis) Update(key string, input *Authorization) error { bt, err := bson.Marshal(input) if err != nil { return err } _, err = p.redisClient.SetEX(p.ctx, key, bt, p.ttl).Result() if err != nil { return err } _, err = p.redisClient.Publish(p.ctx, p.updateChannel, key).Result() return err } func (p *provider_redis) Delete(key string) error { cnt, err := p.redisClient.Del(p.ctx, key).Result() if err != nil { return err } if cnt > 0 { _, err = p.redisClient.Publish(p.ctx, p.deleteChannel, key).Result() } return err } func (p *provider_redis) Query(key string) (*Authorization, error) { payload, err := p.redisClient.Get(p.ctx, key).Result() if err == redis.Nil { return nil, nil } else if err != nil { return nil, err } var auth Authorization if err := bson.Unmarshal([]byte(payload), &auth); err != nil { return nil, err } return &auth, nil } func (p *provider_mongo) Update(key string, input *Authorization) error { _, _, err := p.mongoClient.Update(session_collection_name, bson.M{ "key": key, }, bson.M{ "$set": input, "$currentDate": bson.M{ "_ts": bson.M{"$type": "date"}, }, }, options.Update().SetUpsert(true)) return err } func (p *provider_mongo) Delete(key string) error { _, err := p.mongoClient.Delete(session_collection_name, bson.M{ "key": key, }) return err } func (p *provider_mongo) Query(key string) (*Authorization, error) { var auth Authorization err := p.mongoClient.FindOneAs(session_collection_name, bson.M{ "key": key, }, &auth) return &auth, err }