feat: persist and dispatch client command input

This commit is contained in:
2026-09-06 10:40:23 +00:00
parent 8155e5f81f
commit ad564de23f
16 changed files with 836 additions and 22 deletions
+24 -10
View File
@@ -37,18 +37,23 @@ type Options struct {
BusyTimeout time.Duration
TombstoneLimit uint64
QuotaLimits QuotaLimits
MaxScriptBytes uint64
// MaxExecutionSpecBytes bounds the decompressed protobuf retained for an
// accepted command. It is separate from MaxScriptBytes because a script
// body is uploaded in a different table and lifecycle.
MaxExecutionSpecBytes uint64
MaxScriptBytes uint64
}
type Store struct {
db *sql.DB
unlock func() error
dataDir string
identity domain.UUID
tombstoneLimit uint64
quotaLimits QuotaLimits
maxScriptBytes uint64
mu sync.Mutex
db *sql.DB
unlock func() error
dataDir string
identity domain.UUID
tombstoneLimit uint64
quotaLimits QuotaLimits
maxScriptBytes uint64
maxExecutionSpecBytes uint64
mu sync.Mutex
}
// Open recovers an existing spool or creates an empty one. The caller must
@@ -76,6 +81,15 @@ func Open(ctx context.Context, options Options) (*Store, error) {
options.MaxScriptBytes = options.QuotaLimits.CommandTotalBytes
}
}
if options.MaxExecutionSpecBytes == 0 {
options.MaxExecutionSpecBytes = 768 << 10
if options.MaxExecutionSpecBytes > options.QuotaLimits.CommandTotalBytes {
options.MaxExecutionSpecBytes = options.QuotaLimits.CommandTotalBytes
}
}
if options.MaxExecutionSpecBytes > options.QuotaLimits.CommandTotalBytes {
return nil, errors.New("execution specification maximum exceeds client command quota")
}
if options.MaxScriptBytes > options.QuotaLimits.CommandTotalBytes {
return nil, errors.New("script maximum exceeds client command quota")
}
@@ -110,7 +124,7 @@ func Open(ctx context.Context, options Options) (*Store, error) {
}
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
store := &Store{db: db, unlock: unlock, dataDir: options.DataDir, identity: identity, tombstoneLimit: options.TombstoneLimit, quotaLimits: options.QuotaLimits, maxScriptBytes: options.MaxScriptBytes}
store := &Store{db: db, unlock: unlock, dataDir: options.DataDir, identity: identity, tombstoneLimit: options.TombstoneLimit, quotaLimits: options.QuotaLimits, maxScriptBytes: options.MaxScriptBytes, maxExecutionSpecBytes: options.MaxExecutionSpecBytes}
if err := db.PingContext(ctx); err != nil {
_ = store.Close()
return nil, fmt.Errorf("open client spool SQLite: %w", err)