1package cache
2
3import (
4 "sync"
5
6 "github.com/MichaelMure/git-bug/entity"
7 "github.com/MichaelMure/git-bug/entity/dag"
8 "github.com/MichaelMure/git-bug/repository"
9)
10
11var _ entity.Interface[entity.Snapshot, dag.OperationWithApply[entity.Snapshot]] = &withSnapshot[entity.Snapshot, dag.OperationWithApply[entity.Snapshot]]{}
12
13// withSnapshot encapsulate an entity and maintain a snapshot efficiently.
14type withSnapshot[SnapT entity.Snapshot, OpT dag.OperationWithApply[SnapT]] struct {
15 entity.WithCommit[SnapT, OpT]
16 mu sync.Mutex
17 snap *SnapT
18}
19
20func (ws *withSnapshot[SnapT, OpT]) Compile() SnapT {
21 ws.mu.Lock()
22 defer ws.mu.Unlock()
23 if ws.snap == nil {
24 snap := ws.WithCommit.Compile()
25 ws.snap = &snap
26 }
27 return *ws.snap
28}
29
30// Append intercept Bug.Append() to update the snapshot efficiently
31func (ws *withSnapshot[SnapT, OpT]) Append(op OpT) {
32 ws.mu.Lock()
33 defer ws.mu.Unlock()
34
35 ws.WithCommit.Append(op)
36
37 if ws.snap == nil {
38 return
39 }
40
41 op.Apply(*ws.snap)
42 (*ws.snap).AppendOperation(op)
43}
44
45// Commit intercept Bug.Commit() to update the snapshot efficiently
46func (ws *withSnapshot[SnapT, OpT]) Commit(repo repository.ClockedRepo) error {
47 ws.mu.Lock()
48 defer ws.mu.Unlock()
49
50 err := ws.WithCommit.Commit(repo)
51 if err != nil {
52 ws.snap = nil
53 return err
54 }
55
56 return nil
57}