generated from go-masonry/mortar-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mongo_client.go
130 lines (115 loc) · 4 KB
/
mongo_client.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package clients
import (
"context"
"fmt"
"github.com/bevgene/go-currency-rate/app/model"
"github.com/go-masonry/mortar/interfaces/cfg"
"github.com/go-masonry/mortar/interfaces/log"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/fx"
"net"
)
//go:generate mockgen -source=mongo_client.go -destination=mock/mongo_client_mock.go
type (
mongoClientImplDeps struct {
fx.In
Logger log.Logger
Config cfg.Config
Lifecycle fx.Lifecycle
}
LazyMongoClient struct {
Client MongoClient
}
MongoClient interface {
AddRateDocument(context.Context, *model.ExchangeRateDocument) error
GetLatestRateDocument(context.Context) (*model.ExchangeRateDocument, error)
Disconnect(ctx context.Context) error
}
mongoClientImpl struct {
deps mongoClientImplDeps
client *mongo.Client
collection *mongo.Collection
}
)
const (
appNameKey = "mortar.name"
hostKey = "exchangerate.database.host"
portKey = "exchangerate.database.port"
userKey = "exchangerate.database.user"
passwordKey = "exchangerate.database.password"
databaseKey = "exchangerate.database.name"
collectionKey = "exchangerate.database.collection"
)
func CreateMongoClient(deps mongoClientImplDeps) (result *LazyMongoClient, err error) {
appName := deps.Config.Get(appNameKey).String()
dbName := deps.Config.Get(databaseKey).String()
host := deps.Config.Get(hostKey).String()
port := deps.Config.Get(portKey).String()
userName := deps.Config.Get(userKey).String()
password := deps.Config.Get(passwordKey).String()
collectionName := deps.Config.Get(collectionKey).String()
uri := fmt.Sprintf("mongodb://%s/%s", net.JoinHostPort(host, port), dbName)
if len(userName) > 0 && len(password) > 0 {
uri = fmt.Sprintf("mongodb://%s:%s@%s/%s", userName, password, net.JoinHostPort(host, port), dbName)
}
clientOptions := options.Client().ApplyURI(uri).SetAppName(appName)
var clientPtr = new(LazyMongoClient)
var mongoClient *mongo.Client
var collection *mongo.Collection
deps.Lifecycle.Append(fx.Hook{
OnStart: func(ctx context.Context) (startError error) {
if mongoClient, startError = mongo.Connect(ctx, clientOptions); startError != nil {
deps.Logger.WithError(startError).Error(ctx, "failed to create mongo client")
return
}
if startError = mongoClient.Ping(ctx, nil); startError != nil {
deps.Logger.WithError(startError).Error(ctx, "failed to ping mongo db")
}
collection = mongoClient.Database(dbName).Collection(collectionName)
indexModel := mongo.IndexModel{
Keys: bson.D{{"created_at", 1}},
Options: options.Index().SetUnique(true),
}
if _, startError = collection.Indexes().CreateOne(ctx, indexModel); startError != nil {
return
}
clientPtr.Client = &mongoClientImpl{
deps: deps,
client: mongoClient,
collection: collection,
}
return
},
OnStop: func(ctx context.Context) (stopError error) {
if clientPtr.Client != nil {
if stopError = clientPtr.Client.Disconnect(ctx); stopError != nil {
deps.Logger.WithError(stopError).Error(ctx, "failed to disconnect from mongo db")
}
}
return
},
})
result = clientPtr
return
}
func (impl *mongoClientImpl) AddRateDocument(ctx context.Context, document *model.ExchangeRateDocument) (err error) {
_, err = impl.collection.InsertOne(ctx, document)
impl.deps.Logger.WithError(err).WithField("document", document).Error(ctx, "add rate document")
return
}
func (impl *mongoClientImpl) GetLatestRateDocument(ctx context.Context) (result *model.ExchangeRateDocument, err error) {
findOneOptions := options.FindOne()
findOneOptions.SetSort(bson.M{"created_at": -1})
var doc model.ExchangeRateDocument
if err = impl.collection.FindOne(ctx, bson.M{}, findOneOptions).Decode(&doc); err != nil {
impl.deps.Logger.WithError(err).Error(ctx, "failed decoding result")
return
}
result = &doc
return
}
func (impl *mongoClientImpl) Disconnect(ctx context.Context) error {
return impl.client.Disconnect(ctx)
}