oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1// Package store owns persistence: cells, rows, columns, formats and the
2// append-only event log.
3package store
4
5import (
6 "encoding/json"
7
8 "gorm.io/gorm"
9
10 "amadan.net/oficina/sheets/internal/sheets/seal"
11)
12
13// Event kinds. Two, deliberately: conflating them is what made an earlier
14// draft of the leak list wrong.
15const (
16 KindInput = "input"
17 KindRecalc = "recalc"
18)
19
20// InputEvent is a person's edit, before sealing.
21type InputEvent struct {
22 TabID, RowID, ColID uint64
23 ActorID uint64
24 OldRaw, NewRaw string
25}
26
27type inputPayload struct {
28 RowID uint64 `json:"r"`
29 ColID uint64 `json:"c"`
30 OldRaw string `json:"o"`
31 NewRaw string `json:"n"`
32}
33
34// AppendInput writes a sealed input event. Old and new raw input are user
35// content, so the payload is sealed; the row's shape is not.
36func AppendInput(tx *gorm.DB, s *seal.Sealer, e InputEvent) error {
37 body, err := json.Marshal(inputPayload{
38 RowID: e.RowID, ColID: e.ColID, OldRaw: e.OldRaw, NewRaw: e.NewRaw,
39 })
40 if err != nil {
41 return err
42 }
43 sealed, err := s.Seal("event.payload", body)
44 if err != nil {
45 return err
46 }
47 return tx.Create(&Event{
48 Kind: KindInput, TabID: e.TabID, ActorID: e.ActorID,
49 PayloadSealed: sealed,
50 }).Error
51}
52
53// AppendRecalc records that a recalculation pass ran and how wide it was.
54// It carries no values: version history replays inputs and recomputes, which
55// is slower to restore and the only version that stays honest at scale.
56func AppendRecalc(tx *gorm.DB, triggerID uint64, derived int) error {
57 return tx.Create(&Event{
58 Kind: KindRecalc, TriggerID: triggerID, DerivedCount: derived,
59 }).Error
60}
61