mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-27 13:48:49 +08:00

* Add twins redis cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add connectToRedis to twins main and twinCache to twins service Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add tracing to twins cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add twins cache mock and test setup for redis cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add TestTwinSave to redis twins cache tests Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add remove twin redis cache test Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add channels param to CreateDefinition helper method in mocks Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add IDs test to redis twins cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Simplify senml rec array and attribute creation funcs by removing unnecessary params Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Align cache remove twin method with service remove twin method Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add cache funcs to twins save, update and remove Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add def SaveIDs to redis cache and ref to service SaveStates Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add TwinSaveIDs tests for redis cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add cache related env vars desc to README.md Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add twinid bson key constant Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add Update method to cache Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Integrate uuid unification related changes Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Use named arguments in interface method declarations Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Add env vars to docker-compose file Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Make parameter names in interface methods and implementations consistent Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com> * Wrap vars and consts in var and const blocks Signed-off-by: Darko Draskovic <darko.draskovic@gmail.com>
157 lines
3.5 KiB
Go
157 lines
3.5 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package mongodb
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/mainflux/mainflux/twins"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
const (
|
|
statesCollection string = "states"
|
|
twinid = "twinid"
|
|
)
|
|
|
|
type stateRepository struct {
|
|
db *mongo.Database
|
|
}
|
|
|
|
var _ twins.StateRepository = (*stateRepository)(nil)
|
|
|
|
// NewStateRepository instantiates a MongoDB implementation of state
|
|
// repository.
|
|
func NewStateRepository(db *mongo.Database) twins.StateRepository {
|
|
return &stateRepository{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// SaveState persists the state
|
|
func (sr *stateRepository) Save(ctx context.Context, st twins.State) error {
|
|
coll := sr.db.Collection(statesCollection)
|
|
|
|
if _, err := coll.InsertOne(context.Background(), st); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Update persists the state
|
|
func (sr *stateRepository) Update(ctx context.Context, st twins.State) error {
|
|
coll := sr.db.Collection(statesCollection)
|
|
|
|
filter := bson.M{"id": st.ID, twinid: st.TwinID}
|
|
update := bson.M{"$set": st}
|
|
if _, err := coll.UpdateOne(context.Background(), filter, update); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CountStates returns the number of states related to twin
|
|
func (sr *stateRepository) Count(ctx context.Context, tw twins.Twin) (int64, error) {
|
|
coll := sr.db.Collection(statesCollection)
|
|
|
|
filter := bson.M{twinid: tw.ID}
|
|
total, err := coll.CountDocuments(ctx, filter)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return total, nil
|
|
}
|
|
|
|
// RetrieveAll retrieves the subset of states related to twin specified by id
|
|
func (sr *stateRepository) RetrieveAll(ctx context.Context, offset uint64, limit uint64, twinID string) (twins.StatesPage, error) {
|
|
coll := sr.db.Collection(statesCollection)
|
|
|
|
findOptions := options.Find()
|
|
findOptions.SetSkip(int64(offset))
|
|
findOptions.SetLimit(int64(limit))
|
|
|
|
filter := bson.M{twinid: twinID}
|
|
|
|
cur, err := coll.Find(ctx, filter, findOptions)
|
|
if err != nil {
|
|
return twins.StatesPage{}, err
|
|
}
|
|
|
|
results, err := decodeStates(ctx, cur)
|
|
if err != nil {
|
|
return twins.StatesPage{}, err
|
|
}
|
|
|
|
total, err := coll.CountDocuments(ctx, filter)
|
|
if err != nil {
|
|
return twins.StatesPage{}, err
|
|
}
|
|
|
|
return twins.StatesPage{
|
|
States: results,
|
|
PageMetadata: twins.PageMetadata{
|
|
Total: uint64(total),
|
|
Offset: offset,
|
|
Limit: limit,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// RetrieveLast returns the last state related to twin spec by id
|
|
func (sr *stateRepository) RetrieveLast(ctx context.Context, twinID string) (twins.State, error) {
|
|
coll := sr.db.Collection(statesCollection)
|
|
|
|
filter := bson.M{twinid: twinID}
|
|
total, err := coll.CountDocuments(ctx, filter)
|
|
if err != nil {
|
|
return twins.State{}, err
|
|
}
|
|
|
|
findOptions := options.Find()
|
|
var skip int64
|
|
if total > 0 {
|
|
skip = total - 1
|
|
}
|
|
findOptions.SetSkip(skip)
|
|
findOptions.SetLimit(1)
|
|
|
|
cur, err := coll.Find(ctx, filter, findOptions)
|
|
if err != nil {
|
|
return twins.State{}, err
|
|
}
|
|
|
|
results, err := decodeStates(ctx, cur)
|
|
if err != nil {
|
|
return twins.State{}, err
|
|
}
|
|
|
|
if len(results) < 1 {
|
|
return twins.State{}, nil
|
|
}
|
|
return results[0], nil
|
|
}
|
|
|
|
func decodeStates(ctx context.Context, cur *mongo.Cursor) ([]twins.State, error) {
|
|
defer cur.Close(ctx)
|
|
|
|
var results []twins.State
|
|
for cur.Next(ctx) {
|
|
var elem twins.State
|
|
if err := cur.Decode(&elem); err != nil {
|
|
return []twins.State{}, nil
|
|
}
|
|
results = append(results, elem)
|
|
}
|
|
|
|
if err := cur.Err(); err != nil {
|
|
return []twins.State{}, nil
|
|
}
|
|
return results, nil
|
|
}
|