fix(tenant): Defer plugin seeding until after transaction commits

The post_save signal was trying to seed plugins before the tenant's
schema migrations had completed, causing a 500 error when accepting
tenant invitations. Using transaction.on_commit() ensures the schema
and tables exist before seeding.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-03 16:11:51 -05:00
parent 55cb97ca0d
commit 5244e16279

View File

@@ -4,36 +4,26 @@ Core App Signals
Handles automatic setup tasks when tenants are created. Handles automatic setup tasks when tenants are created.
""" """
import logging import logging
from django.db import transaction
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@receiver(post_save, sender='core.Tenant') def _seed_plugins_for_tenant(tenant_schema_name):
def seed_platform_plugins_on_tenant_create(sender, instance, created, **kwargs):
""" """
Seed platform plugins when a new tenant is created. Internal function to seed platform plugins for a tenant.
Called after transaction commits to ensure schema tables exist.
This ensures new tenants have access to all marketplace plugins immediately.
""" """
if not created:
return
# Skip public schema
if instance.schema_name == 'public':
return
# Defer the import to avoid circular imports
from django.db import connection
from django_tenants.utils import schema_context from django_tenants.utils import schema_context
from schedule.models import PluginTemplate from schedule.models import PluginTemplate
from django.utils import timezone from django.utils import timezone
logger.info(f"Seeding platform plugins for new tenant: {instance.schema_name}") logger.info(f"Seeding platform plugins for new tenant: {tenant_schema_name}")
try: try:
with schema_context(instance.schema_name): with schema_context(tenant_schema_name):
# Import the plugin definitions from the seed command # Import the plugin definitions from the seed command
from schedule.management.commands.seed_platform_plugins import get_platform_plugins from schedule.management.commands.seed_platform_plugins import get_platform_plugins
@@ -62,6 +52,28 @@ def seed_platform_plugins_on_tenant_create(sender, instance, created, **kwargs):
) )
created_count += 1 created_count += 1
logger.info(f"Created {created_count} platform plugins for tenant: {instance.schema_name}") logger.info(f"Created {created_count} platform plugins for tenant: {tenant_schema_name}")
except Exception as e: except Exception as e:
logger.error(f"Failed to seed plugins for tenant {instance.schema_name}: {e}") logger.error(f"Failed to seed plugins for tenant {tenant_schema_name}: {e}")
@receiver(post_save, sender='core.Tenant')
def seed_platform_plugins_on_tenant_create(sender, instance, created, **kwargs):
"""
Seed platform plugins when a new tenant is created.
This ensures new tenants have access to all marketplace plugins immediately.
Uses transaction.on_commit() to defer seeding until after the schema is
fully created and migrations have run.
"""
if not created:
return
# Skip public schema
if instance.schema_name == 'public':
return
# Defer the seeding until after the transaction commits
# This ensures the schema and all tables exist before we try to use them
schema_name = instance.schema_name
transaction.on_commit(lambda: _seed_plugins_for_tenant(schema_name))