intersystems / intersystems/ipm

Routine database mappings not honored when deploying obj code

Open
#1,242 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
ObjectScript
Stars
41
Forks
29
Avg merge
23h 54m
Merged PRs (30d)
4

Description

The Issue in IPM
Summary: IPM doesn't honor routine database mappings when loading deployed (compiled-only) .obj code. It calls %Studio.Project:InstallFromFile() without directing output to the mapped database, causing .obj routines to land in the wrong database on systems where routine mappings point elsewhere.

Root Cause
In Document.cls:188

set sc = ##class(%Studio.Project).InstallFromFile(tDeployedProjectPath, "")
InstallFromFile with "" writes routines to the current namespace's default routine database. However, many deployments use routine mappings (via Config.MapRoutines) to direct specific routine prefixes to a different database — for example, a dedicated "driver" database. IPM is already aware of mappings (it has ResourceIsMappedToDefaultDB() at line 574 and can create mappings via %IPM.Utils.Module), but it doesn't use them when calling InstallFromFile.

On deployments where the mapped database differs from the default, the .obj routines get written to the wrong database on first install. A second install works because by then IPM's own mapping-setup phase has committed the mappings and the namespace resolves correctly.

Our Workaround
In our installer, we currently call InstallFromFile again after IPM's lifecycle completes, by which point mappings are guaranteed to be in place. This is brittle and duplicates work.

Suggested Improvement for IPM
Option A — Respect existing mappings during deployed-resource load:

Before calling InstallFromFile, IPM should ensure that any routine mappings declared in the module's module.xml are committed first. The lifecycle currently applies mappings in a separate phase (OnConfigureMappings), but the deployed-resource load can execute before that phase completes. Reordering so that mapping configuration runs before deployed resource loading would fix this without API changes.

Option B — Allow specifying a target database in the resource processor:

Add an optional Database attribute to elements in module.xml:

The Document processor would then switch to that database (or resolve via %SYS.Namespace:GetRoutineDest()) before calling InstallFromFile. This gives module authors explicit control without relying on namespace mappings being pre-configured.
Option C — Use GetRoutineDest() to resolve per-routine:

At line 188, instead of a single InstallFromFile call, iterate the deployed project's items, resolve each routine's mapped database via ##class(%SYS.Namespace).GetRoutineDest(, routineName), and load into the correct database. IPM already has this lookup logic in ResourceIsMappedToDefaultDB (line 574) — it just needs to apply it during load, not only for conflict detection.

Contributor guide

Open the contributing guide

Research direction

Read Document.cls around line 188 and trace the deployed-resource lifecycle through OnConfigureMappings. Compare this path with ResourceIsMappedToDefaultDB at line 574 and the module.xml mapping declarations, then reproduce a first install where routine mappings target a non-default database. Done means deployed .obj routines land in their mapped database on the first install without a duplicate installer pass.

Written by the indexing model from the issue text.

Assessment

Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.