app.model.strategy_execution_log module

Sampled persistence of DSL strategy executions.

Every call to DslStrategy.calculate_points produces a result + a node trace + a duration. Persisting all of them would inflate the database in production (the engine processes high-volume scoring events), so a sampler chooses a fraction of OK runs and ALL failures to keep around for audit + post-mortem of “why did this strategy emit X points?”.

The trace itself is the same dict the interpreter already builds via _RunState.trace; it is stored as JSONB to keep it queryable.

class app.model.strategy_execution_log.StrategyExecutionLog(*, id=<factory>, created_at=<factory>, updated_at=<factory>, apiKey_used=None, oauth_user_id=None, strategyId, strategyVersion, strategyType, realmId=None, externalGameId=None, externalTaskId=None, externalUserId=None, status, errorCode=None, points=None, caseName=None, durationMs, nodesExecuted, trace=None, sampled, parentStrategyId=None, notes=None)[source]

Bases: BaseModel

One row per sampled DSL execution.

Parameters:
  • id (Annotated[str, FieldInfoMetadata(primary_key=PydanticUndefined, nullable=PydanticUndefined, foreign_key=PydanticUndefined, ondelete=PydanticUndefined, unique=PydanticUndefined, index=PydanticUndefined, sa_type=UUID(), sa_column=PydanticUndefined, sa_column_args=PydanticUndefined, sa_column_kwargs={'primary_key': True, 'index': True})])

  • created_at (Annotated[datetime, FieldInfoMetadata(primary_key=PydanticUndefined, nullable=PydanticUndefined, foreign_key=PydanticUndefined, ondelete=PydanticUndefined, unique=PydanticUndefined, index=PydanticUndefined, sa_type=DateTime(timezone=True), sa_column=PydanticUndefined, sa_column_args=PydanticUndefined, sa_column_kwargs={'server_default': <sqlalchemy.sql.functions.now at 0x7fa8900484a0; now>})])

  • updated_at (Annotated[datetime, FieldInfoMetadata(primary_key=PydanticUndefined, nullable=PydanticUndefined, foreign_key=PydanticUndefined, ondelete=PydanticUndefined, unique=PydanticUndefined, index=PydanticUndefined, sa_type=DateTime(timezone=True), sa_column=PydanticUndefined, sa_column_args=PydanticUndefined, sa_column_kwargs={'server_default': <sqlalchemy.sql.functions.now at 0x7fa88fa2a840; now>, 'onupdate': <sqlalchemy.sql.functions.now at 0x7fa88fa2ad20; now>})])

  • apiKey_used (Annotated[str | None, FieldInfoMetadata(primary_key=PydanticUndefined, nullable=True, foreign_key=apikey.apiKey, ondelete=PydanticUndefined, unique=PydanticUndefined, index=PydanticUndefined, sa_type=PydanticUndefined, sa_column=PydanticUndefined, sa_column_args=PydanticUndefined, sa_column_kwargs=PydanticUndefined)])

  • oauth_user_id (Annotated[str | None, FieldInfoMetadata(primary_key=PydanticUndefined, nullable=True, foreign_key=oauthusers.provider_user_id, ondelete=PydanticUndefined, unique=PydanticUndefined, index=PydanticUndefined, sa_type=PydanticUndefined, sa_column=PydanticUndefined, sa_column_args=PydanticUndefined, sa_column_kwargs=PydanticUndefined)])

strategyId

UUID of the StrategyDefinition row that executed. Stored as plain string (no FK) so a strategy can be hard-deleted without cascading away its audit history.

Type:

str

strategyVersion

Snapshot of the version at execution time; together with strategyId pins the AST that ran even if the row was later edited to v+1.

Type:

int

strategyType

DSL_FULL or DSL_EXTEND – helps partition dashboards by execution flavour.

Type:

str

realmId

Tenant. Indexed for per-realm queries from the runbook (“show me the last failed run of strategy X”).

Type:

str

externalGameId/externalTaskId/externalUserId

The scoring event coordinates. Kept verbatim so an admin can reproduce the run via /simulate.

Type:

str

status

ok / error / timeout / limit.

Type:

str

errorCode

DSL_* code from app/core/exceptions.py when status != ok; nullable otherwise.

Type:

str

points

Computed points; nullable when status != ok.

Type:

numeric

caseName

case_name returned to the caller.

Type:

str

durationMs

Wall-clock duration in milliseconds.

Type:

numeric

nodesExecuted

Count of AST nodes visited; used to spot runaway rules even within the 1000-node hard cap.

Type:

int

trace

Same per-node trace the simulate endpoint returns – node ids, evaluated branches, intermediate values. Bounded by the interpreter’s node cap so the column stays small enough for JSONB.

Type:

jsonb

sampled

True for rows that came in via the sampler, False for rows persisted because the run failed (errors are always kept regardless of the sample rate).

Type:

bool

parentStrategyId

For DSL_EXTEND runs, the built-in strategy id wrapped. Nullable for DSL_FULL.

Type:

str

model_config: ClassVar[ConfigDict] = {'from_attributes': True, 'read_from_attributes': True, 'read_with_orm_mode': True, 'registry': PydanticUndefined, 'table': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].