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
occ app:enable openconnector (chain-E feature/i18n-complete-translations + Repair step)
- 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)
- Confirm magic tables NOT created:
SELECT 1 FROM information_schema.tables WHERE table_name = 'oc_openregister_table_65_223';
→ empty result
- 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
Problem
ImportHandleronly callsMagicMapper::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
ensureTableForRegisterSchemainsideMagicMapper::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_loginConductionNL/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
occ app:enable openconnector(chain-E feature/i18n-complete-translations + Repair step)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, callensureTableForRegisterSchemaonce 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
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