forked from topfreegames/khan
/
prune.go
162 lines (140 loc) · 4.95 KB
/
prune.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
150
151
152
153
154
155
156
157
158
159
160
161
162
// khan
// https://github.com/topfreegames/khan
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license
// Copyright © 2016 Top Free Games <backend@tfgco.com>
package models
import (
"fmt"
"github.com/topfreegames/khan/log"
"github.com/topfreegames/khan/util"
"github.com/uber-go/zap"
)
// PruneStats show stats about what has been pruned
type PruneStats struct {
PendingApplicationsPruned int
PendingInvitesPruned int
DeniedMembershipsPruned int
DeletedMembershipsPruned int
}
//GetStats returns a formatted message
func (ps *PruneStats) GetStats() string {
return fmt.Sprintf(
"-Pending Applications: %d\n-Pending Invites: %d\n-Denied Memberships: %d\n-Deleted Memberships: %d\n",
ps.PendingApplicationsPruned,
ps.PendingInvitesPruned,
ps.DeniedMembershipsPruned,
ps.DeletedMembershipsPruned,
)
}
// PruneOptions has all the prunable memberships TTL
type PruneOptions struct {
GameID string
PendingApplicationsExpiration int
PendingInvitesExpiration int
DeniedMembershipsExpiration int
DeletedMembershipsExpiration int
}
func runAndReturnRowsAffected(query string, db DB, args ...interface{}) (int, error) {
res, err := db.Exec(query, args...)
if err != nil {
return 0, err
}
rows, err := res.RowsAffected()
return int(rows), err
}
func prunePendingApplications(options *PruneOptions, db DB, logger zap.Logger) (int, error) {
query := `DELETE FROM memberships m WHERE
m.game_id=$1 AND
m.deleted_at=0 AND
m.approved=FALSE AND
m.denied=FALSE AND
m.requestor_id=m.player_id AND
m.updated_at < $2`
updatedAt := util.NowMilli() - int64(options.PendingApplicationsExpiration*1000)
return runAndReturnRowsAffected(query, db, options.GameID, updatedAt)
}
func prunePendingInvites(options *PruneOptions, db DB, logger zap.Logger) (int, error) {
query := `DELETE FROM memberships m WHERE
m.game_id=$1 AND
m.deleted_at=0 AND
m.approved=FALSE AND
m.denied=FALSE AND
m.requestor_id != m.player_id AND
m.updated_at < $2`
updatedAt := util.NowMilli() - int64(options.PendingInvitesExpiration*1000)
return runAndReturnRowsAffected(query, db, options.GameID, updatedAt)
}
func pruneDeniedMemberships(options *PruneOptions, db DB, logger zap.Logger) (int, error) {
query := `DELETE FROM memberships m WHERE
m.game_id=$1 AND
m.denied=TRUE AND
m.updated_at < $2`
updatedAt := util.NowMilli() - int64(options.DeniedMembershipsExpiration*1000)
return runAndReturnRowsAffected(query, db, options.GameID, updatedAt)
}
func pruneDeletedMemberships(options *PruneOptions, db DB, logger zap.Logger) (int, error) {
query := `DELETE FROM memberships m WHERE
m.game_id=$1 AND
m.deleted_at > 0 AND
m.updated_at < $2`
updatedAt := util.NowMilli() - int64(options.DeletedMembershipsExpiration*1000)
return runAndReturnRowsAffected(query, db, options.GameID, updatedAt)
}
// PruneStaleData off of Khan's database
func PruneStaleData(options *PruneOptions, db DB, logger zap.Logger) (*PruneStats, error) {
log.I(logger, "Pruning stale data...", func(cm log.CM) {
cm.Write(
zap.String("GameID", options.GameID),
zap.Int("PendingApplicationsExpiration", options.PendingApplicationsExpiration),
zap.Int("PendingInvitesExpiration", options.PendingInvitesExpiration),
zap.Int("DeniedMembershipsExpiration", options.DeniedMembershipsExpiration),
zap.Int("DeletedMembershipsExpiration", options.DeletedMembershipsExpiration),
)
})
pendingApplicationsPruned, err := prunePendingApplications(options, db, logger)
if err != nil {
log.E(logger, "Failed to prune stale pending applications.", func(cm log.CM) {
cm.Write(zap.Error(err))
})
return nil, err
}
pendingInvitesPruned, err := prunePendingInvites(options, db, logger)
if err != nil {
log.E(logger, "Failed to prune stale pending invites.", func(cm log.CM) {
cm.Write(zap.Error(err))
})
return nil, err
}
deniedMembershipsPruned, err := pruneDeniedMemberships(options, db, logger)
if err != nil {
log.E(logger, "Failed to prune stale denied memberships.", func(cm log.CM) {
cm.Write(zap.Error(err))
})
return nil, err
}
deletedMembershipsPruned, err := pruneDeletedMemberships(options, db, logger)
if err != nil {
log.E(logger, "Failed to prune stale deleted memberships.", func(cm log.CM) {
cm.Write(zap.Error(err))
})
return nil, err
}
stats := &PruneStats{
PendingApplicationsPruned: pendingApplicationsPruned,
PendingInvitesPruned: pendingInvitesPruned,
DeniedMembershipsPruned: deniedMembershipsPruned,
DeletedMembershipsPruned: deletedMembershipsPruned,
}
log.I(logger, "Pruned stale data succesfully.", func(cm log.CM) {
cm.Write(
zap.String("GameID", options.GameID),
zap.Int("PendingApplicationsPruned", stats.PendingApplicationsPruned),
zap.Int("PendingInvitesPruned", stats.PendingInvitesPruned),
zap.Int("DeniedMembershipsPruned", stats.DeniedMembershipsPruned),
zap.Int("DeletedMembershipsPruned", stats.DeletedMembershipsPruned),
)
})
return stats, nil
}