Skip to content

Magic table not created for schemas without seed-data (logs come up missing post-import) #1615

@rubenvdlinde

Description

@rubenvdlinde

Problem

ImportHandler only calls MagicMapper::ensureTableForRegisterSchema() from inside the seed-objects loop (lib/Service/Configuration/ImportHandler.php:3175-3204). Schemas with an empty seed-objects array therefore never get their per-schema magic table provisioned during register import.

The fallback path is lazy: the first write against the schema triggers ensureTableForRegisterSchema inside MagicMapper::saveObject. For schemas a user actively writes to (entity-style — source, job, mapping, synchronization), this works.

For schemas written to only by internal services (log-style — call_log, job_log, synchronization_log, synchronization_contract_log in ConductionNL/openconnector), the lazy-create only fires when the service runs end-to-end. If anything earlier in the chain swallows an error (see ConductionNL/openconnector controller-id type bug we filed alongside), the saveObject never runs, the table never gets created, and the dashboard reads zero forever.

Reproducer

  1. occ app:enable openconnector (chain-E feature/i18n-complete-translations + Repair step)
  2. Confirm schemas imported:
    SELECT id, slug FROM oc_openregister_schemas
      WHERE slug IN ('call_log','job_log','synchronization_log','synchronization_contract_log');
    
    → returns 4 rows (IDs 223 / 224 / 225 / 226 on this instance)
  3. Confirm magic tables NOT created:
    SELECT 1 FROM information_schema.tables WHERE table_name = 'oc_openregister_table_65_223';
    
    → empty result
  4. Try to write a call_log via ObjectService::saveObject(register: 'openconnector', schema: 'call_log', ...):
    → throws "relation oc_openregister_table_65_223 does not exist"

(In practice CallService::call() never reaches saveObject because SourcesController::test() returns 404 early — separate openconnector bug. But the deeper invariant remains: tables should exist after import for every schema, not lazily on first write.)

Proposed

Move the ensureTableForRegisterSchema() call OUT of the seed-objects loop and into the per-schema import loop, so every imported schema gets its table provisioned regardless of whether seed data is present.

Concretely in ImportHandler::importFromApp() (or wherever the per-schema iteration lives — there are a few entry points): after the schema is saved and the register registers it, call ensureTableForRegisterSchema once for that (register, schema) pair. The seed-objects loop can keep its existing pre-create call inside as a no-op safety (table already exists).

Why this is high-value

  • Dashboards / reports that aggregate log-style schemas show empty data even after the integration ran successfully
  • Any schema added "for logs" or "for events" silently breaks until someone manually writes the first object
  • Lazy-create papers over a real invariant: the post-import state should be "any saveObject for any imported schema works"

Discovered while investigating an empty openconnector dashboard (ConductionNL/openconnector#838) where Newman tests ran but no logs landed.

Suggested opsx change name

eager-magic-table-creation-on-schema-import

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions