package dbreads import ( "fmt" "time" "github.com/carlosframework/platform/internal/dbdoor" ) // How a read ended (result.json's state, spec §5.6). const ( StateDone = "done" StateFailed = "failed" StateRefused = "refused" StateCancelled = "cancelled" ) // The fixed code vocabulary the console may read. const ( CodeNothingReplicated = "nothing-replicated" CodeHistoryGone = "history-gone" CodeCheckFailed = "check-failed" CodeChangedTwice = "changed-twice" CodeTooLarge = "too-large" CodeNoRoom = "no-room" CodeSQLError = "sql-error" CodeTimeout = "timeout" CodeOutputCap = "output-cap" CodeRecordChanged = "record-changed" CodeMoving = "moving" CodeInterrupted = "interrupted" ) var codesByState = map[string]map[string]bool{ StateDone: {"": true, CodeOutputCap: true}, StateFailed: {CodeNothingReplicated: true, CodeHistoryGone: true, CodeCheckFailed: true, CodeChangedTwice: true, CodeTooLarge: true, CodeNoRoom: true, CodeSQLError: true, CodeTimeout: true, CodeInterrupted: true}, StateRefused: {CodeRecordChanged: true, CodeMoving: true}, StateCancelled: {"": true}, } // Result is db-reads//result.json, written only after every chunk is // confirmed. LastSeq is the last chunk's sequence number; a done read has at // least one chunk, the last of which is sealed as last. type Result struct { State string `json:"state"` Code string `json:"code"` Box string `json:"box"` LastSeq int64 `json:"last_seq"` Started time.Time `json:"started"` Ended time.Time `json:"ended"` Sealed string `json:"sealed"` } // Valid is the shape the console checks before it relays a result. func (r Result) Valid() error { codes, ok := codesByState[r.State] switch { case !ok: return fmt.Errorf("dbreads: unknown state %q", r.State) case !codes[r.Code]: return fmt.Errorf("dbreads: code %q is not one of state %s's", r.Code, r.State) case r.LastSeq < 0, r.State == StateDone && r.LastSeq < 1: return fmt.Errorf("dbreads: last_seq %d for state %s", r.LastSeq, r.State) } return nil } // Picked is db-reads//picked: the owner (J3). type Picked struct { Box string `json:"box"` Boot string `json:"boot"` Nonce string `json:"nonce"` Deadline time.Time `json:"deadline"` } // Summary is the result's sealed half, which only the CLI can open (§5.6). type Summary struct { TXID uint64 `json:"txid"` // the copy's newest transaction At time.Time `json:"at"` // that transaction's time, from its LTX header Oldest time.Time `json:"oldest"` // history-gone: the earliest --at that works Restored int64 `json:"restored"` // too-large: the restored size Cap int64 `json:"cap"` // too-large: the box's cap Error string `json:"error"` // sql-error: SQLite's text; check-failed: the detail Bytes int64 `json:"bytes"` // the output's plaintext byte count SHA256 string `json:"sha256"` // the output's plaintext SHA-256, hex // Files is a pull's planned files in order (plan 3); empty for a query. Files []dbdoor.LTXFile `json:"files,omitempty"` }