44 "context"
55 "github.com/deso-protocol/core/lib"
66 "github.com/deso-protocol/state-consumer/consumer"
7+ "github.com/golang/glog"
78 "github.com/pkg/errors"
89 "github.com/uptrace/bun"
910)
@@ -25,18 +26,48 @@ type PGPkidEntryUtxoOps struct {
2526 UtxoOperation
2627}
2728
29+ type LeaderScheduleEntry struct {
30+ SnapshotAtEpochNumber uint64 `pg:",use_zero"`
31+ LeaderIndex uint16 `pg:",use_zero"`
32+ ValidatorPKID string `pg:",use_zero"`
33+ BadgerKey []byte `pg:",pk,use_zero"`
34+ }
35+
36+ type PGLeaderScheduleEntry struct {
37+ bun.BaseModel `bun:"table:leader_schedule_entry"`
38+ LeaderScheduleEntry
39+ }
40+
2841// Convert the Diamond DeSo encoder to the PG struct used by bun.
29- func PkidEncoderToPGStruct (pkidEntry * lib.PKIDEntry , keyBytes []byte , params * lib.DeSoParams ) PkidEntry {
42+ func PkidEntryEncoderToPGStruct (pkidEntry * lib.PKIDEntry , keyBytes []byte , params * lib.DeSoParams ) PkidEntry {
3043 return PkidEntry {
3144 Pkid : consumer .PublicKeyBytesToBase58Check (pkidEntry .PKID [:], params ),
3245 PublicKey : consumer .PublicKeyBytesToBase58Check (pkidEntry .PublicKey [:], params ),
3346 BadgerKey : keyBytes ,
3447 }
3548}
3649
50+ // Convert the leader schedule entry to the PG struct used by bun.
51+ func LeaderScheduleEncoderToPGStruct (validatorPKID * lib.PKID , keyBytes []byte , params * lib.DeSoParams ,
52+ ) * LeaderScheduleEntry {
53+ prefixRemovedKeyBytes := keyBytes [1 :]
54+ if len (prefixRemovedKeyBytes ) != 10 {
55+ glog .Errorf ("LeaderScheduleEncoderToPGStruct: Invalid key length: %d" , len (prefixRemovedKeyBytes ))
56+ return nil
57+ }
58+ epochNumber := lib .DecodeUint64 (prefixRemovedKeyBytes [:8 ])
59+ leaderIndex := lib .DecodeUint16 (prefixRemovedKeyBytes [8 :10 ])
60+ return & LeaderScheduleEntry {
61+ ValidatorPKID : consumer .PublicKeyBytesToBase58Check (validatorPKID [:], params ),
62+ SnapshotAtEpochNumber : epochNumber ,
63+ LeaderIndex : leaderIndex ,
64+ BadgerKey : keyBytes ,
65+ }
66+ }
67+
3768// PostBatchOperation is the entry point for processing a batch of post entries. It determines the appropriate handler
3869// based on the operation type and executes it.
39- func PkidBatchOperation (entries []* lib.StateChangeEntry , db * bun.DB , params * lib.DeSoParams ) error {
70+ func PkidEntryBatchOperation (entries []* lib.StateChangeEntry , db * bun.DB , params * lib.DeSoParams ) error {
4071 // We check before we call this function that there is at least one operation type.
4172 // We also ensure before this that all entries have the same operation type.
4273 operationType := entries [0 ].OperationType
@@ -61,7 +92,7 @@ func bulkInsertPkidEntry(entries []*lib.StateChangeEntry, db *bun.DB, operationT
6192
6293 // Loop through the entries and convert them to PGPostEntry.
6394 for ii , entry := range uniqueEntries {
64- pgEntrySlice [ii ] = & PGPkidEntry {PkidEntry : PkidEncoderToPGStruct (entry .Encoder .(* lib.PKIDEntry ), entry .KeyBytes , params )}
95+ pgEntrySlice [ii ] = & PGPkidEntry {PkidEntry : PkidEntryEncoderToPGStruct (entry .Encoder .(* lib.PKIDEntry ), entry .KeyBytes , params )}
6596 }
6697
6798 query := db .NewInsert ().Model (& pgEntrySlice )
@@ -95,3 +126,75 @@ func bulkDeletePkidEntry(entries []*lib.StateChangeEntry, db *bun.DB, operationT
95126
96127 return nil
97128}
129+
130+ func PkidBatchOperation (entries []* lib.StateChangeEntry , db * bun.DB , params * lib.DeSoParams ) error {
131+ // We check before we call this function that there is at least one operation type.
132+ // We also ensure before this that all entries have the same operation type.
133+ operationType := entries [0 ].OperationType
134+ var err error
135+ if operationType == lib .DbOperationTypeDelete {
136+ err = bulkDeletePkid (entries , db , operationType )
137+ } else {
138+ err = bulkInsertPkid (entries , db , operationType , params )
139+ }
140+ if err != nil {
141+ return errors .Wrapf (err , "entries.PostBatchOperation: Problem with operation type %v" , operationType )
142+ }
143+ return nil
144+ }
145+
146+ // bulkInsertPkid inserts a batch of PKIDs into the database.
147+ func bulkInsertPkid (entries []* lib.StateChangeEntry , db * bun.DB , operationType lib.StateSyncerOperationType , params * lib.DeSoParams ) error {
148+ // Track the unique entries we've inserted so we don't insert the same entry twice.
149+ uniqueEntries := consumer .UniqueEntries (entries )
150+
151+ uniqueLeaderScheduleEntries := consumer .FilterEntriesByPrefix (
152+ uniqueEntries , lib .Prefixes .PrefixSnapshotLeaderSchedule )
153+ // NOTE: if we need to support parsing other indexes for PKIDs beyond LeaderSchedule,
154+ // we will need to filter the uniqueEntries by the appropriate prefix and then convert
155+ // the entries to the appropriate PG struct.
156+ // Create a new array to hold the bun struct.
157+ pgEntrySlice := make ([]* PGLeaderScheduleEntry , len (uniqueLeaderScheduleEntries ))
158+
159+ // Loop through the entries and convert them to PGPostEntry.
160+ for ii , entry := range uniqueLeaderScheduleEntries {
161+ leaderScheduleEntry := LeaderScheduleEncoderToPGStruct (entry .Encoder .(* lib.PKID ), entry .KeyBytes , params )
162+ if leaderScheduleEntry == nil {
163+ glog .Errorf ("bulkInsertPkid: Error converting LeaderScheduleEntry to PG struct" )
164+ continue
165+ }
166+ pgEntrySlice [ii ] = & PGLeaderScheduleEntry {LeaderScheduleEntry : * leaderScheduleEntry }
167+ }
168+
169+ query := db .NewInsert ().Model (& pgEntrySlice )
170+
171+ if operationType == lib .DbOperationTypeUpsert {
172+ query = query .On ("CONFLICT (badger_key) DO UPDATE" )
173+ }
174+
175+ if _ , err := query .Returning ("" ).Exec (context .Background ()); err != nil {
176+ return errors .Wrapf (err , "entries.bulkInsertPkid: Error inserting entries" )
177+ }
178+ return nil
179+ }
180+
181+ // bulkDeletePKID deletes a batch of PKIDs from the database.
182+ func bulkDeletePkid (entries []* lib.StateChangeEntry , db * bun.DB , operationType lib.StateSyncerOperationType ) error {
183+ // Track the unique entries we've inserted so we don't insert the same entry twice.
184+ uniqueEntries := consumer .UniqueEntries (entries )
185+
186+ // Transform the entries into a list of keys to delete.
187+ keysToDelete := consumer .KeysToDelete (uniqueEntries )
188+ leaderSchedKeysToDelete := consumer .FilterKeysByPrefix (keysToDelete , lib .Prefixes .PrefixSnapshotLeaderSchedule )
189+
190+ // Execute the delete query.
191+ if _ , err := db .NewDelete ().
192+ Model (& LeaderScheduleEntry {}).
193+ Where ("badger_key IN (?)" , bun .In (leaderSchedKeysToDelete )).
194+ Returning ("" ).
195+ Exec (context .Background ()); err != nil {
196+ return errors .Wrapf (err , "entries.bulkDeletePkid: Error deleting entries" )
197+ }
198+
199+ return nil
200+ }
0 commit comments