Integrate account sync with API, background tasks, and user creation
Integration Components:
1. Manual API Endpoints (admin-only):
- POST /api/v1/admin/accounts/sync (full sync)
- POST /api/v1/admin/accounts/sync/{account_name} (single account)
2. Scheduled Background Sync:
- Hourly background task (wait_for_account_sync)
- Registered in castle_start() lifecycle
- Automatically syncs new accounts from Beancount to Castle DB
3. Auto-sync on User Account Creation:
- Updated get_or_create_user_account() in crud.py
- Uses sync_single_account_from_beancount() for consistency
- Ensures receivable/payable accounts are synced when users register
Flow:
- User associates wallet → creates receivable/payable in Beancount
→ syncs to Castle DB → permissions can be granted
- Admin manually syncs → all Beancount accounts added to Castle DB
- Hourly task → catches any accounts created directly in Beancount
This ensures Beancount remains the source of truth while Castle DB
maintains metadata for permissions and user associations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
cbdd5f3779
commit
4a3922895e
4 changed files with 173 additions and 10 deletions
53
tasks.py
53
tasks.py
|
|
@ -95,6 +95,59 @@ async def scheduled_daily_reconciliation():
|
|||
raise
|
||||
|
||||
|
||||
async def scheduled_account_sync():
|
||||
"""
|
||||
Scheduled task that runs hourly to sync accounts from Beancount to Castle DB.
|
||||
|
||||
This ensures Castle DB stays in sync with Beancount (source of truth) by
|
||||
automatically adding any new accounts created in Beancount to Castle's
|
||||
metadata database for permission tracking.
|
||||
"""
|
||||
from .account_sync import sync_accounts_from_beancount
|
||||
|
||||
logger.info(f"[CASTLE] Running scheduled account sync at {datetime.now()}")
|
||||
|
||||
try:
|
||||
stats = await sync_accounts_from_beancount(force_full_sync=False)
|
||||
|
||||
if stats["accounts_added"] > 0:
|
||||
logger.info(
|
||||
f"[CASTLE] Account sync: Added {stats['accounts_added']} new accounts"
|
||||
)
|
||||
|
||||
if stats["errors"]:
|
||||
logger.warning(
|
||||
f"[CASTLE] Account sync: {len(stats['errors'])} errors encountered"
|
||||
)
|
||||
for error in stats["errors"][:5]: # Log first 5 errors
|
||||
logger.error(f" - {error}")
|
||||
|
||||
return stats
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[CASTLE] Error in scheduled account sync: {e}")
|
||||
raise
|
||||
|
||||
|
||||
async def wait_for_account_sync():
|
||||
"""
|
||||
Background task that periodically syncs accounts from Beancount to Castle DB.
|
||||
|
||||
Runs hourly to ensure Castle DB stays in sync with Beancount.
|
||||
"""
|
||||
logger.info("[CASTLE] Account sync background task started")
|
||||
|
||||
while True:
|
||||
try:
|
||||
# Run sync
|
||||
await scheduled_account_sync()
|
||||
except Exception as e:
|
||||
logger.error(f"[CASTLE] Account sync error: {e}")
|
||||
|
||||
# Wait 1 hour before next sync
|
||||
await asyncio.sleep(3600) # 3600 seconds = 1 hour
|
||||
|
||||
|
||||
def start_daily_reconciliation_task():
|
||||
"""
|
||||
Initialize the daily reconciliation task.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue