generated from coulomb/repo-seed
feat(db): add dev seed script for ActivityDefinition — T12
src/activity_core/seed.py: inserts one example ActivityDefinition
('example-heartbeat', cron every minute, static context source,
log_message task template). Idempotent — skips by name on re-run.
Run with:
ACTCORE_DB_URL=postgresql+asyncpg://actcore:actcore@localhost:5433/actcore \
python -m activity_core.seed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
88
src/activity_core/seed.py
Normal file
88
src/activity_core/seed.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""Dev seed script — inserts fixture data for local development.
|
||||
|
||||
Usage:
|
||||
ACTCORE_DB_URL=postgresql+asyncpg://actcore:actcore@localhost:5433/actcore \
|
||||
python -m activity_core.seed
|
||||
|
||||
Safe to re-run: skips rows that already exist (matched by name).
|
||||
Never run against production.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
|
||||
|
||||
from activity_core.db import make_engine
|
||||
from activity_core.orm import ActivityDefinition # noqa: F401 — registers metadata
|
||||
|
||||
|
||||
SEED_DEFINITIONS = [
|
||||
{
|
||||
"id": uuid.UUID("00000000-0000-0000-0000-000000000001"),
|
||||
"name": "example-heartbeat",
|
||||
"enabled": True,
|
||||
"trigger_type": "cron",
|
||||
"trigger_config": {
|
||||
"trigger_type": "cron",
|
||||
"cron_expression": "* * * * *", # every minute
|
||||
"timezone": "UTC",
|
||||
"jitter_seconds": 0,
|
||||
"misfire_policy": "skip",
|
||||
},
|
||||
"context_sources": [
|
||||
{
|
||||
"name": "stub",
|
||||
"type": "static",
|
||||
"config": {"value": {"ping": "pong"}},
|
||||
}
|
||||
],
|
||||
"task_templates": [
|
||||
{
|
||||
"task_type": "log_message",
|
||||
"condition": None,
|
||||
"params_template": {"message": "heartbeat from {context.stub.ping}"},
|
||||
}
|
||||
],
|
||||
"dedupe_key_strategy": "skip",
|
||||
"version": 1,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
async def seed(db_url: str | None = None) -> None:
|
||||
engine = make_engine(db_url)
|
||||
Session = async_sessionmaker(engine, expire_on_commit=False)
|
||||
|
||||
async with Session() as session:
|
||||
async with session.begin():
|
||||
for defn in SEED_DEFINITIONS:
|
||||
existing = await session.scalar(
|
||||
select(ActivityDefinition).where(
|
||||
ActivityDefinition.name == defn["name"]
|
||||
)
|
||||
)
|
||||
if existing:
|
||||
print(f" skip {defn['name']!r} (already exists, id={existing.id})")
|
||||
continue
|
||||
|
||||
session.add(ActivityDefinition(**defn))
|
||||
print(f" insert {defn['name']!r} (id={defn['id']})")
|
||||
|
||||
await engine.dispose()
|
||||
print("done.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
url = os.environ.get("ACTCORE_DB_URL")
|
||||
if not url:
|
||||
print(
|
||||
"error: set ACTCORE_DB_URL before running this script\n"
|
||||
" e.g. ACTCORE_DB_URL=postgresql+asyncpg://actcore:actcore@localhost:5433/actcore",
|
||||
file=sys.stderr,
|
||||
)
|
||||
sys.exit(1)
|
||||
asyncio.run(seed(url))
|
||||
@@ -52,7 +52,7 @@ tasks:
|
||||
state_hub_task_id: 491a6903-8189-43bb-958f-4d16abc84f8e
|
||||
- id: T12
|
||||
title: Seed one example ActivityDefinition
|
||||
status: todo
|
||||
status: done
|
||||
state_hub_task_id: f24662ff-4a26-48bd-b997-57e7586c7f11
|
||||
- id: T13
|
||||
title: Scaffold Python worker project
|
||||
|
||||
Reference in New Issue
Block a user