package main import ( "context" "encoding/hex" "errors" "fmt" "sort" "git.michelsen.id/chron/core" ) type InProcEntryStore struct { entries map[core.EntryID]core.Entry } func (e *InProcEntryStore) Store(ctx context.Context, entry core.Entry) error { if _, ok := e.entries[entry.EntryID]; ok { return errors.New("entry already exists") } e.entries[entry.EntryID] = entry return nil } func (e *InProcEntryStore) Load(ctx context.Context, id core.EntryID) (core.Entry, error) { entry, ok := e.entries[id] if !ok { return core.Entry{}, errors.New("entry does not exist") } return entry, nil } func (e *InProcEntryStore) Exists(ctx context.Context, id core.EntryID) (bool, error) { _, ok := e.entries[id] return ok, nil } func (e *InProcEntryStore) Delete(ctx context.Context, id core.EntryID) error { if _, ok := e.entries[id]; !ok { return errors.New("entry does not exist") } delete(e.entries, id) return nil } type InProcReferenceStore struct { references map[string]core.EntryID } func (r *InProcReferenceStore) Set(ctx context.Context, name string, entryID core.EntryID) error { r.references[name] = entryID return nil } func (r *InProcReferenceStore) Get(ctx context.Context, name string) (core.EntryID, bool, error) { entryID, ok := r.references[name] if !ok { return core.EntryID{}, false, nil } return entryID, true, nil } func (r *InProcReferenceStore) Delete(ctx context.Context, name string) error { if _, ok := r.references[name]; !ok { return errors.New("reference does not exist") } delete(r.references, name) return nil } func main() { ctx := context.TODO() entryStore := InProcEntryStore{ entries: make(map[core.EntryID]core.Entry), } referenceStore := InProcReferenceStore{ references: make(map[string]core.EntryID), } ledger, err := core.NewLedger(&entryStore, &referenceStore) if err != nil { fmt.Println(err) return } for i := range 1000000 { data := fmt.Sprintf("test%d", i) err = ledger.Append(ctx, []byte(data)) if err != nil { fmt.Println(err) return } } entries := make([]core.Entry, 0, len(entryStore.entries)) for _, e := range entryStore.entries { entries = append(entries, e) } sort.Slice(entries, func(i, j int) bool { if entries[i].Timestamp.Equal(entries[j].Timestamp) { return hex.EncodeToString(entries[i].EntryID[:]) < hex.EncodeToString(entries[j].EntryID[:]) } return entries[i].Timestamp.Before(entries[j].Timestamp) }) headID, ok, err := referenceStore.Get(ctx, "HEAD") if err != nil { fmt.Println("get HEAD:", err) return } if !ok { fmt.Println("HEAD reference not set") return } isZero32 := func(b [32]byte) bool { for _, v := range b { if v != 0 { return false } } return true } curID := headID for { ent, err := entryStore.Load(ctx, curID) if err != nil { return } if isZero32(ent.Parents) { break } // Follow the linked list backwards curID = core.EntryID(ent.Parents) } }