package repository import ( "codeword/internal/models" "context" "encoding/json" "github.com/go-redis/redis/v8" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/readpref" "time" ) type CodewordRepository struct { mdb *mongo.Collection rdb *redis.Client } func NewCodewordRepository(deps Deps) *CodewordRepository { return &CodewordRepository{mdb: deps.Mdb, rdb: deps.Rdb} } // сохраняем полученные данные о пользователе и подписи в бд func (r *CodewordRepository) StoreRecoveryRecord(ctx context.Context, deps models.StoreRecDeps) (string, error) { newID := primitive.NewObjectID() signID := deps.Key + newID.Hex() record := models.RestoreRequest{ ID: newID, UserID: deps.UserID, Email: deps.Email, Sign: deps.Key, SignUrl: deps.Url, SignID: signID, CreatedAt: time.Now(), } _, err := r.mdb.InsertOne(ctx, record) if err != nil { return "", err } return newID.Hex(), nil } // добавляем в очередь данные для отправки на почту в редис func (r *CodewordRepository) InsertToQueue(ctx context.Context, deps models.RecEmailDeps) error { sendLockKey := "email:sendLock:" + deps.Email ttl := 5 * time.Minute lockSuccess, err := r.rdb.SetNX(ctx, sendLockKey, "1", ttl).Result() if err != nil { return err } if !lockSuccess { return ErrAlreadyReported } task := models.RecoveryRecord{ ID: deps.ID, UserID: deps.UserID, Email: deps.Email, Key: deps.SignWithID, } taskBytes, err := json.Marshal(task) if err != nil { return err } return r.rdb.Set(ctx, "email:task:"+deps.Email, taskBytes, ttl).Err() } // получаем данные юзера по подписи func (r *CodewordRepository) GetRecoveryRecord(ctx context.Context, key string) (*models.RestoreRequest, error) { var restoreRequest models.RestoreRequest filter := bson.M{"sign_id": key} err := r.mdb.FindOne(ctx, filter).Decode(&restoreRequest) if err != nil { return nil, err } return &restoreRequest, nil } // пингует в монгу чтобы проверить подключение func (r *CodewordRepository) Ping(ctx context.Context) error { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() if err := r.mdb.Database().Client().Ping(ctx, readpref.Primary()); err != nil { return err } if err := r.rdb.Ping(ctx).Err(); err != nil { return err } return nil }