-
Notifications
You must be signed in to change notification settings - Fork 0
/
mongo_game_storage.go
149 lines (127 loc) · 3.36 KB
/
mongo_game_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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"context"
"fmt"
"github.com/google/uuid"
. "go.mongodb.org/mongo-driver/bson"
mgo "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
"os"
"time"
)
type mongoSessionStorage struct {
mClient *mgo.Client
mColl *mgo.Collection
}
func NewMongoSessionStorage() *mongoSessionStorage {
mUser, mPass, mHost := os.Getenv("MONGO_USER"), os.Getenv("MONGO_PASS"), os.Getenv("MONGO_HOST")
mDBName := os.Getenv("MONGO_DBNAME")
mConnUrl := fmt.Sprintf(
"mongodb+srv://%s:%s@%s/%s?retryWrites=true&w=majority",
mUser,
mPass,
mHost,
mDBName,
)
mConnOpts := options.Client()
mConnOpts.ApplyURI(mConnUrl)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
mClient, err := mgo.Connect(ctx, mConnOpts)
if err != nil {
log.Fatal(err)
}
if err = mClient.Ping(ctx, nil); err != nil {
log.Fatal("failed to connect to mongodb: ", err)
}
return &mongoSessionStorage{
mClient: mClient,
mColl: ensureCollectionAndIndexes(mClient),
}
}
func (i *mongoSessionStorage) StoreSession(session *GameInstance) error {
gameId, err := uuid.Parse(session.GameId.Value)
if err != nil {
return err
}
_, err = i.mColl.UpdateOne(
context.Background(),
M{"game_id": M{"eq": gameId}}, //Update only game session with matching uuid
session,
options.Update().SetUpsert(true),
)
if err != nil {
log.Println("failed to store session in mongo: ", err)
return err
}
return nil
}
func (i *mongoSessionStorage) GetSession(id uuid.UUID) (*GameInstance, error) {
singleRes := i.mColl.FindOne(
context.Background(),
M{"game_id": M{"eq": id.String()}}, //Get only game session with matching uuid
)
if err := singleRes.Err(); err != nil {
log.Println("failed to fetch session data from mongo: ", err)
return nil, err
}
ret := new(GameInstance)
err := singleRes.Decode(ret)
if err != nil {
log.Println("failed to decode session data from mongo: ", err)
return nil, err
}
return ret, nil
}
func (i *mongoSessionStorage) CloseSession(id uuid.UUID) error {
_, err := i.mColl.DeleteOne(
context.Background(),
M{"game_id": M{"eq": id.String()}}, //Delete only game session with matching uuid
)
if err != nil {
log.Println("failed to delete session data from mongo: ", err)
}
return err
}
func (i *mongoSessionStorage) CheckExistence(id uuid.UUID) (bool, error) {
n, err := i.mColl.CountDocuments(
context.Background(),
M{"game_id": M{"eq": id.String()}},
)
return n > 0, err
}
func (i *mongoSessionStorage) NumberOfGames() (uint, error) {
n, err := i.mColl.CountDocuments(
context.Background(),
M{}, // Empty filter to count everything
)
return uint(n), err
}
func ensureCollectionAndIndexes(mClient *mgo.Client) *mgo.Collection {
mDB := mClient.Database(os.Getenv("MONGO_DBNAME"))
err := mDB.CreateCollection(context.Background(), "avalonGames")
if err != nil {
//Collection already exists?
if _, exist := err.(mgo.CommandError); exist {
//Yes, no need to create one
return mDB.Collection("avalonGames")
} else {
//No, its generic error
log.Fatal(err)
}
}
mColl := mDB.Collection("avalonGames")
_, err = mColl.Indexes().CreateOne(
context.Background(),
mgo.IndexModel{
Keys: M{"game_id": 1},
Options: options.Index().
SetUnique(true),
},
)
if err != nil {
log.Fatal("failed to create mongo indexes: ", err)
}
return mColl
}