summaryrefslogtreecommitdiff
diff options
authorMiguel Pires <miguel.pires@canonical.com>2023-07-28 09:34:50 +0100
committerMiguel Pires <miguelpires94@gmail.com>2023-08-01 14:25:48 +0100
commitab6d918d8be99b437e902674bd4bf3806d1f0e2b (patch)
treee54e7dcc9b6b24f90eab312cc8d914fd04e7748c
parent0b69df78e4a9b8d9c603fccbed4fbdacaf591a25 (diff)
aspects: optimise aspect tx Get
Cache a copy of the transaction's databag so that a new one doesn't have to be created and all the deltas applied.
-rw-r--r--aspects/transaction.go32
1 files changed, 23 insertions, 9 deletions
diff --git a/aspects/transaction.go b/aspects/transaction.go
index dde36b2dad..0eaa2eb717 100644
--- a/aspects/transaction.go
+++ b/aspects/transaction.go
@@ -28,9 +28,12 @@ type DatabagWrite func(JSONDataBag) error
// Transaction performs read and writes to a databag in an atomic way.
type Transaction struct {
pristine JSONDataBag
- deltas []map[string]interface{}
schema Schema
+ modified JSONDataBag
+ deltas []map[string]interface{}
+ appliedDeltas int
+
readDatabag DatabagRead
writeDatabag DatabagWrite
mu sync.RWMutex
@@ -65,17 +68,26 @@ func (t *Transaction) Get(path string, value interface{}) error {
t.mu.RLock()
defer t.mu.RUnlock()
- // if there are changes, create a copy before applying (for isolation)
- bag := t.pristine
- if len(t.deltas) != 0 {
- bag = t.pristine.Copy()
+ // if there aren't any changes, just use the pristine bag
+ if len(t.deltas) == 0 {
+ return t.pristine.Get(path, value)
+ }
- if err := applyDeltas(bag, t.deltas); err != nil {
- return err
- }
+ // if there are changes, use a cached bag with modifications to do the Get
+ if t.modified == nil {
+ t.modified = t.pristine.Copy()
+ t.appliedDeltas = 0
+ }
+
+ // apply new changes since the last get
+ if err := applyDeltas(t.modified, t.deltas[t.appliedDeltas:]); err != nil {
+ t.modified = nil
+ t.appliedDeltas = 0
+ return err
}
+ t.appliedDeltas = len(t.deltas)
- return bag.Get(path, value)
+ return t.modified.Get(path, value)
}
// Commit applies the previous writes and validates the final databag. If any
@@ -113,7 +125,9 @@ func (t *Transaction) Commit() error {
}
t.pristine = pristine
+ t.modified = nil
t.deltas = nil
+ t.appliedDeltas = 0
return nil
}