@@ -44,7 +44,8 @@ import (
44
44
// b. UPDATED we simply update it with the new value.
45
45
// c. REMOVED it means that at this point in the ledger the entry is removed
46
46
// so updating it returns an error.
47
- // d. RESTORED we update it with the new value but keep the change type as RESTORED.
47
+ // d. RESTORED we update it with the new value but keep the change type as
48
+ // RESTORED.
48
49
// 3. If the change is REMOVE it checks if any change connected to given entry
49
50
// is already in the cache. If not, it adds REMOVE change. Otherwise, if
50
51
// existing change is:
@@ -56,26 +57,42 @@ import (
56
57
// change means the entry exists in a DB.
57
58
// c. REMOVED it returns error because we can't remove an entry that was
58
59
// already removed.
59
- // d. RESTORED it means the entry doesn't exist in the DB, so it's a noop
60
- // so remove the entry from the cache.
61
- // 4. If the change is RESTORED it checks if any change related to the given entry
62
- // already exists in the cache. If not, it adds the RESTORED change. Otherwise,
63
- // returns an error since restoration is only possible for previously archived/evicted
64
- // entries. If the entry was created, updated or removed within the same ledger, restoration
65
- // is not possible.
60
+ // d. RESTORED depending on the change compactor's configuration, we may or
61
+ // may not emit a REMOVE change type for an entry that was restored earlier
62
+ // in the ledger.
63
+ // 4. If the change is RESTORED it checks if any change related to the given
64
+ // entry already exists in the cache. If not, it adds the RESTORED change.
65
+ // Otherwise, it returns an error because only expired entries can be
66
+ // restored. If the entry was created, updated or removed in the same
67
+ // ledger, it's not expired.
66
68
type ChangeCompactor struct {
67
69
// ledger key => Change
68
- cache map [string ]Change
69
- encodingBuffer * xdr.EncodingBuffer
70
- emitExpiredEntriesRemovedChange bool
70
+ cache map [string ]Change
71
+ encodingBuffer * xdr.EncodingBuffer
72
+ config * ChangeCompactorConfig
73
+ }
74
+
75
+ type ChangeCompactorConfig struct {
76
+ // Determines whether the change compactor emits a REMOVED change when an expired entry
77
+ // is restored and then removed within the same ledger.
78
+ // If set to true, a REMOVED change is emitted; if false, REMOVED change is suppressed.
79
+ EmitExpiredEntryRemovedChange bool
80
+ }
81
+
82
+ func NewChangeCompactorDefaultConfig () * ChangeCompactorConfig {
83
+ return & ChangeCompactorConfig {
84
+ // By default, set it to true to enable the change compactor
85
+ // to emit REMOVED change for expired entries.
86
+ EmitExpiredEntryRemovedChange : true ,
87
+ }
71
88
}
72
89
73
90
// NewChangeCompactor returns a new ChangeCompactor.
74
- func NewChangeCompactor (emitExpiredEntriesRemovedChange bool ) * ChangeCompactor {
91
+ func NewChangeCompactor (config * ChangeCompactorConfig ) * ChangeCompactor {
75
92
return & ChangeCompactor {
76
- cache : make (map [string ]Change ),
77
- encodingBuffer : xdr .NewEncodingBuffer (),
78
- emitExpiredEntriesRemovedChange : emitExpiredEntriesRemovedChange ,
93
+ cache : make (map [string ]Change ),
94
+ encodingBuffer : xdr .NewEncodingBuffer (),
95
+ config : config ,
79
96
}
80
97
}
81
98
@@ -104,16 +121,10 @@ func (c *ChangeCompactor) AddChange(change Change) error {
104
121
// addCreatedChange adds a change to the cache, but returns an error if create
105
122
// change is unexpected.
106
123
func (c * ChangeCompactor ) addCreatedChange (change Change ) error {
107
- // safe, since we later cast to string (causing a copy)
108
- key , err := change .Post .LedgerKey ()
124
+ ledgerKey , err := c .getLedgerKey (change .Post )
109
125
if err != nil {
110
- return errors . Wrap ( err , "error getting ledger key for new entry" )
126
+ return err
111
127
}
112
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
113
- if err != nil {
114
- return errors .Wrap (err , "error marshaling ledger key for new entry" )
115
- }
116
-
117
128
ledgerKeyString := string (ledgerKey )
118
129
119
130
existingChange , exist := c .cache [ledgerKeyString ]
@@ -136,7 +147,7 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error {
136
147
// If existing type is removed it means that this entry does exist
137
148
// in a DB so we update entry change.
138
149
c .cache [ledgerKeyString ] = Change {
139
- Type : key .Type ,
150
+ Type : change .Type ,
140
151
Pre : existingChange .Pre ,
141
152
Post : change .Post ,
142
153
ChangeType : xdr .LedgerEntryChangeTypeLedgerEntryUpdated ,
@@ -148,19 +159,26 @@ func (c *ChangeCompactor) addCreatedChange(change Change) error {
148
159
return nil
149
160
}
150
161
151
- // addUpdatedChange adds a change to the cache, but returns an error if update
152
- // change is unexpected.
153
- func (c * ChangeCompactor ) addUpdatedChange (change Change ) error {
162
+ func (c * ChangeCompactor ) getLedgerKey (ledgerEntry * xdr.LedgerEntry ) ([]byte , error ) {
154
163
// safe, since we later cast to string (causing a copy)
155
- key , err := change . Post .LedgerKey ()
164
+ key , err := ledgerEntry .LedgerKey ()
156
165
if err != nil {
157
- return errors .Wrap (err , "error getting ledger key for updated entry" )
166
+ return nil , errors .Wrap (err , "error getting ledger key for new entry" )
158
167
}
159
168
ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
160
169
if err != nil {
161
- return errors .Wrap (err , "error marshaling ledger key for updated entry" )
170
+ return nil , errors .Wrap (err , "error marshaling ledger key for new entry" )
162
171
}
172
+ return ledgerKey , nil
173
+ }
163
174
175
+ // addUpdatedChange adds a change to the cache, but returns an error if update
176
+ // change is unexpected.
177
+ func (c * ChangeCompactor ) addUpdatedChange (change Change ) error {
178
+ ledgerKey , err := c .getLedgerKey (change .Post )
179
+ if err != nil {
180
+ return err
181
+ }
164
182
ledgerKeyString := string (ledgerKey )
165
183
166
184
existingChange , exist := c .cache [ledgerKeyString ]
@@ -174,15 +192,16 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error {
174
192
// If existing type is created it means that this entry does not
175
193
// exist in a DB so we update entry change.
176
194
c .cache [ledgerKeyString ] = Change {
177
- Type : key .Type ,
178
- Pre : existingChange .Pre , // = nil
179
- Post : change .Post ,
195
+ Type : change .Type ,
196
+ Pre : existingChange .Pre , // = nil
197
+ Post : change .Post ,
198
+ ChangeType : existingChange .ChangeType ,
180
199
}
181
200
case xdr .LedgerEntryChangeTypeLedgerEntryUpdated :
182
201
fallthrough
183
202
case xdr .LedgerEntryChangeTypeLedgerEntryRestored :
184
203
c .cache [ledgerKeyString ] = Change {
185
- Type : key .Type ,
204
+ Type : change .Type ,
186
205
Pre : existingChange .Pre ,
187
206
Post : change .Post ,
188
207
ChangeType : existingChange .ChangeType , //keep the existing change type
@@ -202,16 +221,10 @@ func (c *ChangeCompactor) addUpdatedChange(change Change) error {
202
221
// addRemovedChange adds a change to the cache, but returns an error if remove
203
222
// change is unexpected.
204
223
func (c * ChangeCompactor ) addRemovedChange (change Change ) error {
205
- // safe, since we later cast to string (causing a copy)
206
- key , err := change .Pre .LedgerKey ()
224
+ ledgerKey , err := c .getLedgerKey (change .Pre )
207
225
if err != nil {
208
- return errors . Wrap ( err , "error getting ledger key for removed entry" )
226
+ return err
209
227
}
210
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
211
- if err != nil {
212
- return errors .Wrap (err , "error marshaling ledger key for removed entry" )
213
- }
214
-
215
228
ledgerKeyString := string (ledgerKey )
216
229
217
230
existingChange , exist := c .cache [ledgerKeyString ]
@@ -227,7 +240,7 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
227
240
delete (c .cache , ledgerKeyString )
228
241
case xdr .LedgerEntryChangeTypeLedgerEntryUpdated :
229
242
c .cache [ledgerKeyString ] = Change {
230
- Type : key .Type ,
243
+ Type : change .Type ,
231
244
Pre : existingChange .Pre ,
232
245
Post : nil ,
233
246
ChangeType : change .ChangeType ,
@@ -238,9 +251,9 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
238
251
base64 .StdEncoding .EncodeToString (ledgerKey ),
239
252
))
240
253
case xdr .LedgerEntryChangeTypeLedgerEntryRestored :
241
- if c .emitExpiredEntriesRemovedChange {
254
+ if c .config . EmitExpiredEntryRemovedChange {
242
255
c .cache [ledgerKeyString ] = Change {
243
- Type : key .Type ,
256
+ Type : change .Type ,
244
257
Pre : change .Pre ,
245
258
Post : nil ,
246
259
ChangeType : change .ChangeType ,
@@ -259,16 +272,10 @@ func (c *ChangeCompactor) addRemovedChange(change Change) error {
259
272
// addRestoredChange adds a change to the cache, but returns an error if the restore
260
273
// change is unexpected.
261
274
func (c * ChangeCompactor ) addRestoredChange (change Change ) error {
262
- // safe, since we later cast to string (causing a copy)
263
- key , err := change .Post .LedgerKey ()
275
+ ledgerKey , err := c .getLedgerKey (change .Post )
264
276
if err != nil {
265
- return errors . Wrap ( err , "error getting ledger key for updated entry" )
277
+ return err
266
278
}
267
- ledgerKey , err := c .encodingBuffer .UnsafeMarshalBinary (key )
268
- if err != nil {
269
- return errors .Wrap (err , "error marshaling ledger key for updated entry" )
270
- }
271
-
272
279
ledgerKeyString := string (ledgerKey )
273
280
274
281
if _ , exist := c .cache [ledgerKeyString ]; exist {
0 commit comments