feat: atomically journal and deliver authorized native operation outcomes
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
This commit is contained in:
parent
3c5cbfbafe
commit
f0eff0ac92
13 changed files with 583 additions and 28 deletions
31
hub_core/migrations/versions/0006_outcome_outbox.py
Normal file
31
hub_core/migrations/versions/0006_outcome_outbox.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"""Transaction-linked committed outcome delivery.
|
||||
|
||||
Revision ID: 0006_outcome_outbox
|
||||
Revises: 0005_message_identity_aliases
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
revision = '0006_outcome_outbox'
|
||||
down_revision = '0005_message_identity_aliases'
|
||||
branch_labels = depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('runtime_outcome_outbox',
|
||||
sa.Column('id', sa.String(36), sa.ForeignKey('runtime_audit_ledger.id'), primary_key=True),
|
||||
sa.Column('envelope', sa.JSON(), nullable=False),
|
||||
sa.Column('created_at', sa.Float(), nullable=False),
|
||||
sa.Column('attempts', sa.Integer(), nullable=False),
|
||||
sa.Column('next_attempt', sa.Float(), nullable=False),
|
||||
sa.Column('delivered_at', sa.Float(), nullable=True))
|
||||
op.create_index('ix_runtime_outcome_pending','runtime_outcome_outbox',['delivered_at','next_attempt'])
|
||||
|
||||
|
||||
def downgrade():
|
||||
pending = op.get_bind().execute(sa.text(
|
||||
'SELECT id FROM runtime_outcome_outbox WHERE delivered_at IS NULL LIMIT 1'))
|
||||
if pending is None or pending.first() is not None:
|
||||
raise RuntimeError('outcome downgrade requires an online check and a drained outbox')
|
||||
op.drop_index('ix_runtime_outcome_pending',table_name='runtime_outcome_outbox')
|
||||
op.drop_table('runtime_outcome_outbox')
|
||||
Loading…
Add table
Add a link
Reference in a new issue