Skip to content

SQL Schema Atlas

SQL schema map

SQL Server storage в ChokaQ построен вокруг active work, immutable history, operator recovery, lifetime counters, rolling metrics, queue configuration и schema migration metadata.

Default schema name - chokaq.

Tables

TablePurposeHot path?
JobsHotActive work: pending, fetched, processing, delayed retry.Yes
JobsArchiveУспешно завершенные jobs.No
JobsDLQFailed, cancelled, zombie или operator-held jobs.No
StatsSummaryLifetime counters per queue.No
MetricBucketsRecent throughput и failure-rate aggregates.No
QueuesRuntime configuration очередей.Yes, read by workers
SchemaMigrationsApplied ChokaQ SQL schema versions.Startup/ops

JobsHot

JobsHot - единственная таблица, которую воркеры сканируют для поиска executable work. Держать ее маленькой - главное performance decision в модели Three Pillars.

Ключевые колонки:

ColumnMeaning
IdStable job identifier.
QueueQueue partition и operational control boundary.
TypePersisted job type key.
PayloadSerialized job payload.
TagsOptional operator/search metadata.
IdempotencyKeyOptional active-work dedupe key.
PriorityЧем выше значение, тем раньше fetch.
StatusPending, fetched или processing.
AttemptCountЧисло executions, дошедших до Processing.
ScheduledAtUtcFuture eligibility time для delays и retries.
WorkerIdТекущий worker owner после fetch.
HeartbeatUtcProcessing liveness signal.

Важные indexes:

IndexSupports
IX_JobsHot_FetchWorker fetch ordering by queue, priority, schedule, creation time.
IX_JobsHot_IdempotencyUnique active idempotency key.
IX_JobsHot_QueueStatsQueue dashboard counts.
IX_JobsHot_PendingLagQueue lag health checks.
IX_JobsHot_StatusCreatedActive job dashboard view.
IX_JobsHot_FetchedRecoveryAbandoned fetched-job recovery.
IX_JobsHot_ProcessingHeartbeatZombie detection.

JobsArchive

JobsArchive хранит succeeded jobs после успешного final transition. Она не участвует в worker fetch path.

Indexes поддерживают recent history, queue-specific history и tag search. Archive может расти независимо от active work, потому что воркеры не сканируют его для новых jobs.

JobsDLQ

JobsDLQ хранит failed, cancelled, zombie и operator-held jobs. Она питает inspection, edit, resurrection, bulk requeue, bulk purge и failure grouping.

Важные indexes:

IndexSupports
IX_JobsDLQ_DateRecent DLQ view.
IX_JobsDLQ_QueueQueue-scoped DLQ inspection.
IX_JobsDLQ_ReasonFailure taxonomy filtering.
IX_JobsDLQ_TypeType-key failure triage.
IX_JobsDLQ_CreatedAtAge-based cleanup and investigation.

StatsSummary

StatsSummary хранит lifetime counters per queue:

  • succeeded total;
  • failed total;
  • retried total;
  • last activity timestamp.

Это избавляет от пересчета lifetime counters через сканирование Archive и DLQ.

MetricBuckets

MetricBuckets хранит recent completion aggregates. ChokaQ обновляет buckets внутри той же transaction, которая перемещает job в Archive или DLQ.

Так dashboard throughput остается дешевым и стабильным:

  • Archive отвечает на investigation questions;
  • DLQ отвечает на recovery questions;
  • MetricBuckets отвечает на recent-rate questions.

Queues

Queues - runtime control table. Она хранит:

  • queue name;
  • paused/active flags;
  • per-queue zombie timeout;
  • optional max worker budget;
  • last update timestamp.

Workers читают эту таблицу, чтобы не fetch'ить paused queues и enforcing'ить per-queue capacity.

SchemaMigrations

SchemaMigrations записывает applied ChokaQ schema versions. Она превращает first-start bootstrap в auditable operation, а не полагается только на idempotent CREATE TABLE IF MISSING logic.

Архитектурное решение

Почему этот pattern?

Schema разделяет active work и historical evidence. Это держит worker queries маленькими, но сохраняет completed и failed jobs для operators.

Trade-offs

Переходы между таблицами требуют transaction integrity. Implementation должен аккуратно избегать copy-then-delete bugs. ChokaQ использует короткие SQL transactions и OUTPUT, чтобы сделать moves atomic.

Рассмотренные альтернативы

AlternativeBenefitCost
Single Jobs table with status columnПростая model.Hot path деградирует по мере роста history.
Broker-only queueHigh throughput.Менее прозрачное operational state без дополнительного storage.
Archive outside SQLМеньше database.Сложнее debugging и split-brain evidence.

Дополнительные вопросы

Почему не хранить каждое job в одной таблице?
Потому что active fetch queries делили бы indexes и storage с годами history, делая worker path чувствительным к retention.

Почему materialize MetricBuckets?
Потому что dashboard rate windows не должны сканировать mutable history tables или меняться, когда operator purges/requeues DLQ rows.

Главный риск этой schema?
Cross-table moves должны быть atomic. Поэтому final transitions используют database transactions и deleted-row capture.

Лицензия Apache 2.0