Skip to main content

Capabilities

Overview

Available since io.Manager 4.0

The Layout migration is a one-time operation that migrates the legacy Layouts stored by the io.Manager Server to advanced Layouts. Run it once after enabling advanced Layouts on a server that already holds legacy Layouts, so that the io.Connect platforms can find their Global and Workspace Layouts in the new model.

The migration is available only while advanced Layouts are enabled - otherwise, the migration endpoints reject requests with an HTTP 400 status code. You can review and run the migration from the "Migrate legacy layouts" page of the io.Manager Admin UI or via the migration endpoints of the io.Manager Server REST API.

The @interopio/manager-api library exposes the same operations via the getMigration(), getMigrationLayouts(), and runMigration() methods accessible via the advancedLayouts property of an AdminAPI instance.

⚠️ Note that a legacy Layout is migrated only once. Changes made to a legacy Layout after it has been migrated (e.g., while the server is reverted to using legacy Layouts) aren't carried over to its advanced counterpart by a later run. Changes made to advanced Layouts after the migration (saving, sharing, renaming, or deleting a Layout) affect only the advanced Layouts. Once the migration status is "completed-clean", no legacy Layout can be migrated, including legacy Layouts created after the clean run.

Layout Conversion

Each migrated Layout keeps the id, name, type, definition, and disabled fields of the legacy Layout, as well as the users that created and last modified it and the times of creation and last modification. The access information of the migrated Layout is derived from the visibility fields of the legacy Layout:

Access Level Owner Access Entities Legacy Layout
"private" The owner of the legacy Layout. None. Owned by a user and not public.
"public" The user that created the legacy Layout. None. The public property is set to true.
"shared" The user that created the legacy Layout. Each group in accessList, granted "view" access. Common Layout (owner is * or not set) that isn't public and is shared with one or more groups via accessList.

A legacy Layout that fits none of these rows (e.g., a common Layout shared with no groups, or a public Layout with no recorded creator) isn't migrated and is reported as a failure.

The migration doesn't apply the sharing restriction - a legacy Layout that becomes "shared" or "public" is migrated even if its new owner isn't allowed to share Layouts.

Default Global Layouts

A legacy Layout can be marked as default while being public or shared with groups, which designates the same default Global Layout for several users. Advanced Layouts have no default flag - each user has their own default Global Layout. The migration carries the default designation over as follows:

  • An enabled private Global Layout marked as default becomes the default Global Layout of its owner, unless the owner already has a default advanced Layout, in which case the existing default is kept. When a user owns several such Layouts, the most recently modified one becomes the default Global Layout of that user. A default whose owner isn't a known user is dropped without being reported.
  • Any other Layout marked as default is migrated, but loses its default designation.

The migration status reports how many defaults are eligible to be carried over and how many will be dropped, so that you can review them before running the migration. The outcome of the run reports how many defaults were actually assigned.

Previewing

Before running the migration, review the changes it will make on the "Migrate legacy layouts" page of the Admin UI or via the migration endpoints. The GET /advancedLayouts/migration/status endpoint reports the following:

Field Description
carriedDefaultsCount The number of default Global Layouts among the Layouts to be migrated that are eligible to become the default Global Layout of their owner. The defaultsAssignedCount field of the run outcome reports how many were actually assigned.
droppedDefaultsCount The number of default Global Layouts among the Layouts to be migrated that will lose their default designation.
lastRun The outcome of the most recent run. Absent when the migration has never run.
layoutsCount The number of legacy Layouts a run would migrate - the legacy Layouts that haven't been migrated yet.
running Whether a migration run is currently in progress on any io.Manager Server instance.
status The migration status - "completed-clean", "completed-with-failures", or "never-run".

The GET /advancedLayouts/migration/layouts endpoint lists the legacy Layouts a run would migrate. Each item carries the visibility fields of the legacy Layout and an advancedAccessInfo field with the access information the Layout will receive, so that you can verify the owner, access level, and access entities of every Layout before migrating it.

Running

To run the migration, use the "Migrate legacy layouts" page of the Admin UI, or send a request to the POST /advancedLayouts/migration/run endpoint. The run migrates each legacy Layout that hasn't been migrated yet, and reports its outcome:

Field Description
defaultsAssignedCount The number of users whose default Global Layout was set by the run.
defaultsSkippedExistingCount The number of users that kept their existing default Global Layout.
failures The legacy Layouts that the run couldn't migrate, or whose default designation it couldn't carry over, each with the reason for the failure. Contains at most the first 100 failures.
failuresCount The total number of failures, including any beyond the reported failures list.
finishedAt The time when the run finished, in milliseconds since the Unix epoch.
migratedCount The number of legacy Layouts migrated by the run.
skippedCount The number of legacy Layouts skipped because an earlier run already migrated them.

⚠️ Note that the run is also recorded in the audit log.

The pageSize property of the LayoutsMigrationConfig object controls how many legacy Layouts a run reads and writes at a time. The Layouts migrated by each page stay migrated if the run fails later.

Multiple Server Instances

Only one migration run can be in progress at a time across all io.Manager Server instances. Starting a run while another one is in progress is rejected with an HTTP 409 status code.

A run is considered in progress for the time set by the claimStaleness property of the LayoutsMigrationConfig object (10 minutes by default), measured from its start. After that time, a new run can start even if the earlier one is still executing - e.g., because the server instance running it stopped, or because the run takes longer than claimStaleness. Set claimStaleness above the expected duration of a run. Before starting a new run after that time has elapsed, confirm that the earlier run has stopped.

Status & Reruns

After a run, the migration status is one of the following:

Status Description
"completed-clean" The last run reported no failures and left no legacy Layout unmigrated. The migration is complete and can't be run again - further runs are rejected with an HTTP 409 status code.
"completed-with-failures" The last run reported failures, or legacy Layouts that haven't been migrated remain. The migration can be run again.
"never-run" No completed run has been recorded.

A run that fails with an error doesn't change the migration status, but the Layouts it migrated before the error stay migrated and a later run skips them.

Resolving Failures

When a run reports failures, resolve the reported reasons and run the migration again. A new run skips the legacy Layouts that have already been migrated and migrates only the remaining ones.

  • An existing advanced Layout with the same identity is resolved by renaming or deleting that advanced Layout. An existing advanced Layout with the same id is resolved by deleting it.
  • A default designation that couldn't be carried over because the advanced counterpart is disabled is carried over by the next run once the advanced Layout is enabled again.
  • A Layout that couldn't be saved because an advanced Layout with the same identity or id was created while the run was in progress is migrated by the next run once the conflict is resolved.
  • Any other reason means that the stored legacy Layout record is incomplete or damaged, or that two legacy Layouts would become the same advanced Layout. Correct the record directly in the database, because the REST API endpoints for legacy Layouts reject writes while advanced Layouts are enabled.