feat: persist and dispatch client command input
This commit is contained in:
@@ -19,6 +19,7 @@ var (
|
||||
type RecoveryReport struct {
|
||||
EventsChecked uint64
|
||||
ScriptsChecked uint64
|
||||
SpecsChecked uint64
|
||||
}
|
||||
|
||||
// Check verifies state that SQLite's own structural check cannot express. The
|
||||
@@ -34,7 +35,7 @@ func (store *Store) Check(ctx context.Context) (RecoveryReport, error) {
|
||||
if err := checkQuotaCounters(ctx, store.db); err != nil {
|
||||
return RecoveryReport{}, err
|
||||
}
|
||||
return checkPayloads(ctx, store.db, store.maxScriptBytes)
|
||||
return checkPayloads(ctx, store.db, store.maxScriptBytes, store.maxExecutionSpecBytes)
|
||||
}
|
||||
|
||||
func quickCheck(ctx context.Context, database *sql.DB) error {
|
||||
@@ -65,6 +66,7 @@ func checkQuotaCounters(ctx context.Context, database *sql.DB) error {
|
||||
err := database.QueryRowContext(ctx, `SELECT count(*) FROM commands AS c
|
||||
WHERE c.total_charged_bytes != c.base_charged_bytes +
|
||||
COALESCE((SELECT sum(charged_bytes) FROM events WHERE issue_uuid = c.issue_uuid), 0) +
|
||||
COALESCE((SELECT charged_bytes FROM command_specs WHERE issue_uuid = c.issue_uuid), 0) +
|
||||
COALESCE((SELECT charged_bytes FROM scripts WHERE issue_uuid = c.issue_uuid), 0)
|
||||
OR c.output_charged_bytes !=
|
||||
COALESCE((SELECT sum(charged_bytes) FROM events WHERE issue_uuid = c.issue_uuid AND output = 1), 0)`).Scan(&invalid)
|
||||
@@ -81,7 +83,7 @@ OR c.output_charged_bytes !=
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkPayloads(ctx context.Context, database *sql.DB, maxScriptBytes uint64) (RecoveryReport, error) {
|
||||
func checkPayloads(ctx context.Context, database *sql.DB, maxScriptBytes, maxExecutionSpecBytes uint64) (RecoveryReport, error) {
|
||||
var report RecoveryReport
|
||||
rows, err := database.QueryContext(ctx, `SELECT issue_uuid, event_kind, raw_bytes, payload, payload_sha256 FROM events ORDER BY issue_uuid, local_ordinal`)
|
||||
if err != nil {
|
||||
@@ -119,6 +121,35 @@ func checkPayloads(ctx context.Context, database *sql.DB, maxScriptBytes uint64)
|
||||
if err := rows.Close(); err != nil {
|
||||
return report, err
|
||||
}
|
||||
specs, err := database.QueryContext(ctx, `SELECT issue_uuid, raw_bytes, stored_bytes, compression, payload, payload_sha256 FROM command_specs ORDER BY issue_uuid`)
|
||||
if err != nil {
|
||||
return report, err
|
||||
}
|
||||
for specs.Next() {
|
||||
var owner, payload, digest []byte
|
||||
var rawBytes, storedBytes uint64
|
||||
var compression uint32
|
||||
if err := specs.Scan(&owner, &rawBytes, &storedBytes, &compression, &payload, &digest); err != nil {
|
||||
_ = specs.Close()
|
||||
return report, err
|
||||
}
|
||||
computed := immutableDigest(payload)
|
||||
if _, valid := copiedUUID(owner); !valid || compression != 2 || rawBytes == 0 || rawBytes > maxExecutionSpecBytes || storedBytes != uint64(len(payload)) || len(digest) != 32 || !bytes.Equal(computed[:], digest) {
|
||||
_ = specs.Close()
|
||||
return report, ErrStoredPayloadChecksum
|
||||
}
|
||||
if _, err := decompressExecutionSpec(payload, rawBytes, maxExecutionSpecBytes); err != nil {
|
||||
_ = specs.Close()
|
||||
return report, ErrStoredPayloadChecksum
|
||||
}
|
||||
report.SpecsChecked++
|
||||
}
|
||||
if err := specs.Close(); err != nil {
|
||||
return report, err
|
||||
}
|
||||
if err := specs.Err(); err != nil {
|
||||
return report, err
|
||||
}
|
||||
scripts, err := database.QueryContext(ctx, `SELECT issue_uuid, received_raw_bytes, stored_bytes, stored_data FROM scripts ORDER BY issue_uuid`)
|
||||
if err != nil {
|
||||
return report, err
|
||||
|
||||
Reference in New Issue
Block a user