1// Copyright (C) 2019 Storj Labs, Inc.
2// See LICENSE for copying information.
3
4package satellitedb
5
6import (
7	"context"
8	"sync"
9
10	"github.com/zeebo/errs"
11
12	"storj.io/common/lrucache"
13	"storj.io/storj/satellite/console"
14	"storj.io/storj/satellite/satellitedb/dbx"
15)
16
17// ensures that ConsoleDB implements console.DB.
18var _ console.DB = (*ConsoleDB)(nil)
19
20// ConsoleDB contains access to different satellite databases.
21type ConsoleDB struct {
22	apikeysLRUOptions lrucache.Options
23
24	db *satelliteDB
25	tx *dbx.Tx
26
27	methods dbx.Methods
28
29	apikeysOnce *sync.Once
30	apikeys     *apikeys
31}
32
33// Users is getter a for Users repository.
34func (db *ConsoleDB) Users() console.Users {
35	return &users{db.methods}
36}
37
38// Projects is a getter for Projects repository.
39func (db *ConsoleDB) Projects() console.Projects {
40	return &projects{db: db.methods, sdb: db.db}
41}
42
43// ProjectMembers is a getter for ProjectMembers repository.
44func (db *ConsoleDB) ProjectMembers() console.ProjectMembers {
45	return &projectMembers{db.methods, db.db}
46}
47
48// APIKeys is a getter for APIKeys repository.
49func (db *ConsoleDB) APIKeys() console.APIKeys {
50	db.apikeysOnce.Do(func() {
51		db.apikeys = &apikeys{
52			methods: db.methods,
53			lru:     lrucache.New(db.apikeysLRUOptions),
54			db:      db.db,
55		}
56	})
57
58	return db.apikeys
59}
60
61// RegistrationTokens is a getter for RegistrationTokens repository.
62func (db *ConsoleDB) RegistrationTokens() console.RegistrationTokens {
63	return &registrationTokens{db.methods}
64}
65
66// ResetPasswordTokens is a getter for ResetPasswordTokens repository.
67func (db *ConsoleDB) ResetPasswordTokens() console.ResetPasswordTokens {
68	return &resetPasswordTokens{db.methods}
69}
70
71// WithTx is a method for executing and retrying transaction.
72func (db *ConsoleDB) WithTx(ctx context.Context, fn func(context.Context, console.DBTx) error) error {
73	if db.db == nil {
74		return errs.New("DB is not initialized!")
75	}
76
77	return db.db.WithTx(ctx, func(ctx context.Context, tx *dbx.Tx) error {
78		dbTx := &DBTx{
79			ConsoleDB: &ConsoleDB{
80				apikeysLRUOptions: db.apikeysLRUOptions,
81
82				// Need to expose dbx.DB for when database methods need access to check database driver type
83				db:      db.db,
84				tx:      tx,
85				methods: tx,
86
87				apikeysOnce: db.apikeysOnce,
88				apikeys:     db.apikeys,
89			},
90		}
91		return fn(ctx, dbTx)
92	})
93}
94
95// DBTx extends Database with transaction scope.
96type DBTx struct {
97	*ConsoleDB
98}
99
100// Commit is a method for committing and closing transaction.
101func (db *DBTx) Commit() error {
102	if db.tx == nil {
103		return errs.New("begin transaction before commit it!")
104	}
105
106	return db.tx.Commit()
107}
108
109// Rollback is a method for rollback and closing transaction.
110func (db *DBTx) Rollback() error {
111	if db.tx == nil {
112		return errs.New("begin transaction before rollback it!")
113	}
114
115	return db.tx.Rollback()
116}
117