-
Notifications
You must be signed in to change notification settings - Fork 23
/
contacts_container_cache.go
142 lines (115 loc) · 3.22 KB
/
contacts_container_cache.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
package exchange
import (
"context"
"time"
"github.com/alcionai/clues"
"github.com/microsoftgraph/msgraph-sdk-go/models"
"github.com/alcionai/corso/src/internal/common/ptr"
"github.com/alcionai/corso/src/pkg/fault"
"github.com/alcionai/corso/src/pkg/logger"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/services/m365/api/graph"
)
var (
_ graph.ContainerResolver = &contactContainerCache{}
_ containerRefresher = &contactRefresher{}
)
type contactRefresher struct {
getter containerGetter
userID string
}
func (r *contactRefresher) refreshContainer(
ctx context.Context,
id string,
) (graph.CachedContainer, error) {
c, err := r.getter.GetContainerByID(ctx, r.userID, id)
if err != nil {
return nil, clues.Stack(err)
}
f := graph.NewCacheFolder(c, nil, nil)
return &f, nil
}
type contactContainerCache struct {
*containerResolver
enumer containersEnumerator[models.ContactFolderable]
getter containerGetter
userID string
}
func (cfc *contactContainerCache) init(
ctx context.Context,
baseNode string,
baseContainerPath []string,
) error {
if len(baseNode) == 0 {
return clues.NewWC(ctx, "m365 folderID required for base contact folder")
}
if cfc.containerResolver == nil {
cfc.containerResolver = newContainerResolver(&contactRefresher{
userID: cfc.userID,
getter: cfc.getter,
})
}
return cfc.populateContactRoot(ctx, baseNode, baseContainerPath)
}
func (cfc *contactContainerCache) populateContactRoot(
ctx context.Context,
directoryID string,
baseContainerPath []string,
) error {
f, err := cfc.getter.GetContainerByID(ctx, cfc.userID, directoryID)
if err != nil {
return clues.Wrap(err, "fetching root folder")
}
temp := graph.NewCacheFolder(
f,
path.Builder{}.Append(ptr.Val(f.GetId())), // path of IDs
path.Builder{}.Append(baseContainerPath...)) // display location
if err := cfc.addFolder(&temp); err != nil {
return clues.WrapWC(ctx, err, "adding resolver dir")
}
return nil
}
// Populate is utility function for placing cache container
// objects into the Contact Folder Cache
// Function does NOT use Delta Queries as it is not supported
// as of (Oct-07-2022)
func (cfc *contactContainerCache) Populate(
ctx context.Context,
errs *fault.Bus,
baseID string,
baseContainerPath ...string,
) error {
start := time.Now()
logger.Ctx(ctx).Info("populating container cache")
if err := cfc.init(ctx, baseID, baseContainerPath); err != nil {
return clues.Wrap(err, "initializing")
}
el := errs.Local()
containers, err := cfc.enumer.EnumerateContainers(
ctx,
cfc.userID,
baseID)
ctx = clues.Add(ctx, "num_enumerated_containers", len(containers))
if err != nil {
return clues.WrapWC(ctx, err, "enumerating containers")
}
for _, c := range containers {
if el.Failure() != nil {
return el.Failure()
}
cacheFolder := graph.NewCacheFolder(c, nil, nil)
err := cfc.addFolder(&cacheFolder)
if err != nil {
errs.AddRecoverable(
ctx,
clues.StackWC(ctx, err).Label(fault.LabelForceNoBackupCreation))
}
}
if err := cfc.populatePaths(ctx, errs); err != nil {
return clues.Wrap(err, "populating paths")
}
logger.Ctx(ctx).Infow(
"done populating container cache",
"duration", time.Since(start))
return el.Failure()
}