-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
conflicts.go
113 lines (94 loc) · 3.17 KB
/
conflicts.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
package teams
import (
"fmt"
"github.com/keybase/client/go/libkb"
"github.com/keybase/client/go/lru"
"github.com/keybase/client/go/protocol/keybase1"
"golang.org/x/net/context"
)
// Increment to invalidate the disk cache.
const diskStorageVersionConflictInfo = 1
type conflictID struct {
isPublic bool
id keybase1.TeamID
}
func (i conflictID) MemKey() string {
prefix := "r"
if i.isPublic {
prefix = "u"
}
return fmt.Sprintf("%s%s", prefix, i.id)
}
func (i conflictID) DbKey() libkb.DbKey {
return libkb.DbKey{
Typ: libkb.ObjType(libkb.DBImplicitTeamConflictInfo),
Key: i.MemKey(),
}
}
var _ libkb.LRUKeyer = conflictID{}
type rawGetConflictInfo struct {
Status libkb.AppStatus `json:"status"`
ConflictInfo *keybase1.ImplicitTeamConflictInfo `json:"conflict_info"`
}
func (r *rawGetConflictInfo) GetAppStatus() *libkb.AppStatus {
return &r.Status
}
func GetConflictInfo(ctx context.Context, g *libkb.GlobalContext, id keybase1.TeamID, isFullyResolved bool, name keybase1.ImplicitTeamDisplayName) (ret keybase1.ImplicitTeamDisplayName, err error) {
mctx := libkb.NewMetaContext(ctx, g)
defer mctx.Trace(fmt.Sprintf("GetConflictInfo(%s,%v)", id, name), &err)()
ret = name.DeepCopy()
key := conflictID{name.IsPublic, id}
cv, err := g.GetImplicitTeamConflictInfoCacher().Get(ctx, g, key)
if err != nil {
mctx.Debug("In fetching from cache: %s", err.Error())
}
if cv != nil {
if p, ok := cv.(*keybase1.ImplicitTeamConflictInfo); ok {
if p.IsConflict() {
ret.ConflictInfo = p
}
return ret, nil
}
mctx.Debug("Bad element of wrong type from cache: %T", cv)
}
displayName, err := FormatImplicitTeamDisplayName(ctx, g, name)
if err != nil {
return ret, err
}
arg := libkb.NewAPIArg("team/conflict_info")
arg.SessionType = libkb.APISessionTypeREQUIRED
if name.IsPublic {
arg.SessionType = libkb.APISessionTypeOPTIONAL
}
arg.Args = libkb.HTTPArgs{
"tid": libkb.S{Val: string(id)},
"display_name": libkb.S{Val: displayName},
"public": libkb.B{Val: name.IsPublic},
}
var raw rawGetConflictInfo
if err = mctx.G().API.GetDecode(mctx, arg, &raw); err != nil {
return ret, err
}
ci := raw.ConflictInfo
ret.ConflictInfo = ci
// If the team is not fully resolved, and there isn't a conflict, there might
// still become a conflict in the future, so we decide not to cache it.
// Otherwise, the answer stays true indefinitely, so we can cache the value
// without fear of staleness.
if isFullyResolved || ci.IsConflict() {
tmpErr := mctx.G().GetImplicitTeamConflictInfoCacher().Put(ctx, g, key, ci)
if tmpErr != nil {
mctx.Debug("Failed to cached implicit team conflict info: %s", tmpErr.Error())
}
}
return ret, nil
}
func NewImplicitTeamConflictInfoCache(g *libkb.GlobalContext) *lru.Cache {
return lru.NewLRU(g, libkb.ImplicitTeamConflictInfoCacheSize, diskStorageVersionConflictInfo, keybase1.ImplicitTeamConflictInfo{})
}
func NewImplicitTeamConflictInfoCacheAndInstall(g *libkb.GlobalContext) {
cache := NewImplicitTeamConflictInfoCache(g)
g.SetImplicitTeamConflictInfoCacher(cache)
g.AddLogoutHook(cache, "implicitTeamConflictInfoCache")
g.AddDbNukeHook(cache, "implicitTeamConflictInfoCache")
}