/
storage.go
70 lines (59 loc) · 1.65 KB
/
storage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package user
import (
"context"
"cloud.google.com/go/firestore"
"github.com/pkg/errors"
"google.golang.org/api/iterator"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/HalvaPovidlo/halva-services/internal/pkg/user"
fire "github.com/HalvaPovidlo/halva-services/pkg/firestore"
)
const approximateUsersNumber = 10
type storage struct {
*firestore.Client
}
func NewStorage(client *firestore.Client) *storage {
return &storage{
Client: client,
}
}
func (s *storage) Upsert(ctx context.Context, new *user.Item) error {
userRef := s.Collection(fire.UsersCollection).Doc(new.ID)
err := s.RunTransaction(ctx, func(ctx context.Context, tx *firestore.Transaction) error {
userDoc, err := tx.Get(userRef)
switch {
case status.Code(err) == codes.NotFound:
return errors.Wrap(tx.Set(userRef, new), "tx set user doc")
case err != nil:
return errors.Wrap(err, "get user doc")
}
old, err := user.Parse(userDoc)
if err != nil {
return errors.Wrap(err, "parse user doc")
}
old.Username = new.Username
old.Avatar = new.Avatar
return errors.Wrap(tx.Set(userRef, old), "tx set user doc")
})
return errors.Wrap(err, "run upsert user transaction")
}
func (s *storage) All(ctx context.Context) (user.Items, error) {
users := make(user.Items, 0, approximateUsersNumber)
iter := s.Collection(fire.UsersCollection).Documents(ctx)
for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, errors.Wrap(err, "get next iterator")
}
u, err := user.Parse(doc)
if err != nil {
return nil, errors.Wrap(err, "parse user doc")
}
users = append(users, *u)
}
return users, nil
}