|
9 | 9 | "sync"
|
10 | 10 | "time"
|
11 | 11 |
|
| 12 | + "github.com/authzed/spicedb/internal/datastore/common" |
| 13 | + "github.com/authzed/spicedb/pkg/spiceerrors" |
| 14 | + |
12 | 15 | "github.com/google/uuid"
|
13 | 16 | "github.com/hashicorp/go-memdb"
|
14 | 17 |
|
@@ -195,40 +198,72 @@ func (mdb *memdbDatastore) ReadWriteTx(
|
195 | 198 | mdb.Lock()
|
196 | 199 | defer mdb.Unlock()
|
197 | 200 |
|
198 |
| - // Record the changes that were made |
199 |
| - newChanges := datastore.RevisionChanges{ |
200 |
| - Revision: newRevision, |
201 |
| - RelationshipChanges: nil, |
202 |
| - } |
| 201 | + tracked := common.NewChanges(revisions.TimestampIDKeyFunc, datastore.WatchRelationships|datastore.WatchSchema) |
203 | 202 | if tx != nil {
|
204 | 203 | for _, change := range tx.Changes() {
|
205 |
| - if change.Table == tableRelationship { |
| 204 | + switch change.Table { |
| 205 | + case tableRelationship: |
206 | 206 | if change.After != nil {
|
207 | 207 | rt, err := change.After.(*relationship).RelationTuple()
|
208 | 208 | if err != nil {
|
209 | 209 | return datastore.NoRevision, err
|
210 | 210 | }
|
211 |
| - newChanges.RelationshipChanges = append(newChanges.RelationshipChanges, &corev1.RelationTupleUpdate{ |
212 |
| - Operation: corev1.RelationTupleUpdate_TOUCH, |
213 |
| - Tuple: rt, |
214 |
| - }) |
215 |
| - } |
216 |
| - if change.After == nil && change.Before != nil { |
| 211 | + |
| 212 | + if err := tracked.AddRelationshipChange(ctx, newRevision, rt, corev1.RelationTupleUpdate_TOUCH); err != nil { |
| 213 | + return datastore.NoRevision, err |
| 214 | + } |
| 215 | + } else if change.After == nil && change.Before != nil { |
217 | 216 | rt, err := change.Before.(*relationship).RelationTuple()
|
218 | 217 | if err != nil {
|
219 | 218 | return datastore.NoRevision, err
|
220 | 219 | }
|
221 |
| - newChanges.RelationshipChanges = append(newChanges.RelationshipChanges, &corev1.RelationTupleUpdate{ |
222 |
| - Operation: corev1.RelationTupleUpdate_DELETE, |
223 |
| - Tuple: rt, |
224 |
| - }) |
| 220 | + |
| 221 | + if err := tracked.AddRelationshipChange(ctx, newRevision, rt, corev1.RelationTupleUpdate_DELETE); err != nil { |
| 222 | + return datastore.NoRevision, err |
| 223 | + } |
| 224 | + } else { |
| 225 | + return datastore.NoRevision, spiceerrors.MustBugf("unexpected relationship change") |
| 226 | + } |
| 227 | + case tableNamespace: |
| 228 | + if change.After != nil { |
| 229 | + loaded := &corev1.NamespaceDefinition{} |
| 230 | + if err := loaded.UnmarshalVT(change.After.(*namespace).configBytes); err != nil { |
| 231 | + return datastore.NoRevision, err |
| 232 | + } |
| 233 | + |
| 234 | + tracked.AddChangedDefinition(ctx, newRevision, loaded) |
| 235 | + } else if change.After == nil && change.Before != nil { |
| 236 | + tracked.AddDeletedNamespace(ctx, newRevision, change.Before.(*namespace).name) |
| 237 | + } else { |
| 238 | + return datastore.NoRevision, spiceerrors.MustBugf("unexpected namespace change") |
| 239 | + } |
| 240 | + case tableCaveats: |
| 241 | + if change.After != nil { |
| 242 | + loaded := &corev1.CaveatDefinition{} |
| 243 | + if err := loaded.UnmarshalVT(change.After.(*caveat).definition); err != nil { |
| 244 | + return datastore.NoRevision, err |
| 245 | + } |
| 246 | + |
| 247 | + tracked.AddChangedDefinition(ctx, newRevision, loaded) |
| 248 | + } else if change.After == nil && change.Before != nil { |
| 249 | + tracked.AddDeletedCaveat(ctx, newRevision, change.Before.(*caveat).name) |
| 250 | + } else { |
| 251 | + return datastore.NoRevision, spiceerrors.MustBugf("unexpected namespace change") |
225 | 252 | }
|
226 | 253 | }
|
227 | 254 | }
|
228 | 255 |
|
| 256 | + var rc datastore.RevisionChanges |
| 257 | + changes := tracked.AsRevisionChanges(revisions.TimestampIDKeyLessThanFunc) |
| 258 | + if len(changes) > 1 { |
| 259 | + return datastore.NoRevision, spiceerrors.MustBugf("unexpected MemDB transaction with multiple revision changes") |
| 260 | + } else if len(changes) == 1 { |
| 261 | + rc = changes[0] |
| 262 | + } |
| 263 | + |
229 | 264 | change := &changelog{
|
230 | 265 | revisionNanos: newRevision.TimestampNanoSec(),
|
231 |
| - changes: newChanges, |
| 266 | + changes: rc, |
232 | 267 | }
|
233 | 268 | if err := tx.Insert(tableChangelog, change); err != nil {
|
234 | 269 | return datastore.NoRevision, fmt.Errorf("error writing changelog: %w", err)
|
|
0 commit comments