aboutsummaryrefslogtreecommitdiffstats
path: root/cache/cached.go
diff options
context:
space:
mode:
Diffstat (limited to 'cache/cached.go')
-rw-r--r--cache/cached.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/cache/cached.go b/cache/cached.go
new file mode 100644
index 00000000..9f9e170d
--- /dev/null
+++ b/cache/cached.go
@@ -0,0 +1,111 @@
+package cache
+
+import (
+ "sync"
+
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/entity/dag"
+ "github.com/MichaelMure/git-bug/repository"
+ "github.com/MichaelMure/git-bug/util/lamport"
+)
+
+var _ CacheEntity = &CachedEntityBase[dag.Snapshot, dag.Operation]{}
+
+// CachedEntityBase provide the base function of an entity managed by the cache.
+type CachedEntityBase[SnapT dag.Snapshot, OpT dag.Operation] struct {
+ repo repository.ClockedRepo
+ entityUpdated func(id entity.Id) error
+ getUserIdentity getUserIdentityFunc
+
+ mu sync.RWMutex
+ entity dag.Interface[SnapT, OpT]
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) Id() entity.Id {
+ return e.entity.Id()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) Snapshot() SnapT {
+ e.mu.RLock()
+ defer e.mu.RUnlock()
+ return e.entity.Compile()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) notifyUpdated() error {
+ return e.entityUpdated(e.entity.Id())
+}
+
+// ResolveOperationWithMetadata will find an operation that has the matching metadata
+func (e *CachedEntityBase[SnapT, OpT]) ResolveOperationWithMetadata(key string, value string) (entity.Id, error) {
+ e.mu.RLock()
+ defer e.mu.RUnlock()
+ // preallocate but empty
+ matching := make([]entity.Id, 0, 5)
+
+ for _, op := range e.entity.Operations() {
+ opValue, ok := op.GetMetadata(key)
+ if ok && value == opValue {
+ matching = append(matching, op.Id())
+ }
+ }
+
+ if len(matching) == 0 {
+ return "", ErrNoMatchingOp
+ }
+
+ if len(matching) > 1 {
+ return "", entity.NewErrMultipleMatch("operation", matching)
+ }
+
+ return matching[0], nil
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) Validate() error {
+ e.mu.RLock()
+ defer e.mu.RUnlock()
+ return e.entity.Validate()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) Commit() error {
+ e.mu.Lock()
+ err := e.entity.Commit(e.repo)
+ if err != nil {
+ e.mu.Unlock()
+ return err
+ }
+ e.mu.Unlock()
+ return e.notifyUpdated()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) CommitAsNeeded() error {
+ e.mu.Lock()
+ err := e.entity.CommitAsNeeded(e.repo)
+ if err != nil {
+ e.mu.Unlock()
+ return err
+ }
+ e.mu.Unlock()
+ return e.notifyUpdated()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) NeedCommit() bool {
+ e.mu.RLock()
+ defer e.mu.RUnlock()
+ return e.entity.NeedCommit()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) Lock() {
+ e.mu.Lock()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) CreateLamportTime() lamport.Time {
+ return e.entity.CreateLamportTime()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) EditLamportTime() lamport.Time {
+ return e.entity.EditLamportTime()
+}
+
+func (e *CachedEntityBase[SnapT, OpT]) FirstOp() OpT {
+ return e.entity.FirstOp()
+}