Сесия 9: Production Hardening — prop tests (58 invariant-а), fuzz tests (35 сценария), thread safety (SharedLock ref)
CI / test (push) Has been cancelled
CI / verify (push) Has been cancelled
Clients CI / build-server (push) Has been cancelled
Clients CI / test-python (push) Has been cancelled
Clients CI / test-javascript (push) Has been cancelled
Clients CI / test-nim (push) Has been cancelled
Clients CI / test-rust (push) Has been cancelled

This commit is contained in:
2026-05-17 12:37:50 +03:00
parent 19fa760604
commit dc4ad86ee1
4 changed files with 966 additions and 45 deletions
+24 -20
View File
@@ -57,6 +57,9 @@ type
usingExpr*: Node # parsed USING expression
withCheckExpr*: Node # parsed WITH CHECK expression
SharedLock* = ref object
lock*: Lock
ExecutionContext* = ref object
db*: LSMTree
tables*: Table[string, TableDef]
@@ -72,10 +75,10 @@ type
policies*: Table[string, seq[PolicyDef]] # table name -> policies
currentUser*: string
currentRole*: string
sessionVars*: Table[string, string] # session-scoped key/value variables
autoIncCounters*: Table[string, int64] # table.col -> next auto-increment value
sequences*: Table[string, int64] # sequence name -> current value
ctxLock*: Lock # protects tables, views, btrees, ftsIndexes, users, policies, autoIncCounters, sequences
sessionVars*: Table[string, string]
autoIncCounters*: Table[string, int64]
sequences*: Table[string, int64]
sharedLock*: SharedLock # shared across cloned contexts — protects tables, views, btrees, ftsIndexes, users, policies, autoIncCounters, sequences
MigrationRecord* = object
name*: string
@@ -160,9 +163,10 @@ proc newExecutionContext*(db: LSMTree): ExecutionContext =
currentUser: "", currentRole: "",
sessionVars: initTable[string, string](),
autoIncCounters: initTable[string, int64](),
sequences: initTable[string, int64](),
onChange: nil)
initLock(result.ctxLock)
sequences: initTable[string, int64](),
onChange: nil)
result.sharedLock = SharedLock()
initLock(result.sharedLock.lock)
restoreSchema(result)
# ----------------------------------------------------------------------
@@ -348,9 +352,9 @@ proc cloneForConnection*(ctx: ExecutionContext): ExecutionContext =
currentUser: ctx.currentUser, currentRole: ctx.currentRole,
sessionVars: svCopy,
autoIncCounters: ctx.autoIncCounters,
sequences: ctx.sequences,
pendingTxn: nil, onChange: ctx.onChange)
initLock(result.ctxLock)
sequences: ctx.sequences,
pendingTxn: nil, onChange: ctx.onChange)
result.sharedLock = ctx.sharedLock
# ----------------------------------------------------------------------
# Migration Helpers
@@ -1066,26 +1070,26 @@ proc evalExpr*(expr: IRExpr, row: Table[string, string], ctx: ExecutionContext =
if ctx == nil: return "0"
let seqName = evalExpr(expr.irFuncArgs[0], row, ctx)
var val: int64 = 0
acquire(ctx.ctxLock)
acquire(ctx.sharedLock.lock)
try:
if seqName in ctx.sequences:
val = ctx.sequences[seqName]
val += 1
ctx.sequences[seqName] = val
finally:
release(ctx.ctxLock)
release(ctx.sharedLock.lock)
return $val
of "currval":
if expr.irFuncArgs.len < 1:
return "0"
if ctx == nil: return "0"
let seqName = evalExpr(expr.irFuncArgs[0], row, ctx)
acquire(ctx.ctxLock)
acquire(ctx.sharedLock.lock)
try:
if seqName in ctx.sequences:
return $ctx.sequences[seqName]
finally:
release(ctx.ctxLock)
release(ctx.sharedLock.lock)
return "0"
return "0"
of "snowflake_id":
@@ -3524,13 +3528,13 @@ proc executeQueryImpl(ctx: ExecutionContext, astNode: Node, params: seq[WireValu
if col.autoIncrement and col.name notin mutableFields:
let counterKey = stmt.insTarget & "." & col.name
var nextVal: int64 = 1
acquire(ctx.ctxLock)
acquire(ctx.sharedLock.lock)
try:
if counterKey in ctx.autoIncCounters:
nextVal = ctx.autoIncCounters[counterKey]
ctx.autoIncCounters[counterKey] = nextVal + int64(mutableValues.len)
finally:
release(ctx.ctxLock)
release(ctx.sharedLock.lock)
# Insert at position 0 so it becomes the primary storage key
mutableFields.insert(col.name, 0)
for i in 0..<mutableValues.len:
@@ -3545,12 +3549,12 @@ proc executeQueryImpl(ctx: ExecutionContext, astNode: Node, params: seq[WireValu
try:
let intVal = parseInt(providedVal)
let counterKey = stmt.insTarget & "." & col.name
acquire(ctx.ctxLock)
acquire(ctx.sharedLock.lock)
try:
if counterKey notin ctx.autoIncCounters or intVal >= ctx.autoIncCounters[counterKey]:
ctx.autoIncCounters[counterKey] = intVal + 1
finally:
release(ctx.ctxLock)
release(ctx.sharedLock.lock)
except: discard
applyDefaultValues(tbl, mutableFields, mutableValues)
@@ -4280,11 +4284,11 @@ proc executeQuery*(ctx: ExecutionContext, astNode: Node, params: seq[WireValue]
return okResult()
let stmt = astNode.stmts[0]
if isDDL(stmt):
acquire(ctx.ctxLock)
acquire(ctx.sharedLock.lock)
try:
result = executeQueryImpl(ctx, astNode, params)
finally:
release(ctx.ctxLock)
release(ctx.sharedLock.lock)
else:
result = executeQueryImpl(ctx, astNode, params)