refactor: drop compound resourceId end-to-end, remove V25 SDK filters

The previous commit kept a getCompoundResourceId() helper and a pair of
V25 request/response filters that recomposed the legacy "id:id" shape
at the boundary to utopia-php/migration. That was a workaround for the
library still requiring a composite. The library has now been updated
in utopia-php/migration#feat/drop-compound-resource-id to take separate
databaseId/tableId and a separate rootResourceChildId, so the
compromise is no longer needed.

- Worker now reads parentResourceId/resourceId straight from the
  migration document and passes them as separate args to CSV/JSON
  source/destination constructors and to Transfer::run.
- getCompoundResourceId() helper removed.
- Request/V25 and Response/V25 filters removed (their only job was to
  translate the dropped composite shape).
- composer.json pinned to the migration library branch via VCS until
  it ships a tagged release.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jake Barnby
2026-05-01 13:21:15 +12:00
co-authored by Claude Opus 4.7
parent 5462998c2c
commit 5fa348d7ee
6 changed files with 67 additions and 133 deletions
-8
View File
@@ -28,7 +28,6 @@ use Appwrite\Utopia\Request\Filters\V21 as RequestV21;
use Appwrite\Utopia\Request\Filters\V22 as RequestV22;
use Appwrite\Utopia\Request\Filters\V23 as RequestV23;
use Appwrite\Utopia\Request\Filters\V24 as RequestV24;
use Appwrite\Utopia\Request\Filters\V25 as RequestV25;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Filters\V16 as ResponseV16;
use Appwrite\Utopia\Response\Filters\V17 as ResponseV17;
@@ -39,7 +38,6 @@ use Appwrite\Utopia\Response\Filters\V21 as ResponseV21;
use Appwrite\Utopia\Response\Filters\V22 as ResponseV22;
use Appwrite\Utopia\Response\Filters\V23 as ResponseV23;
use Appwrite\Utopia\Response\Filters\V24 as ResponseV24;
use Appwrite\Utopia\Response\Filters\V25 as ResponseV25;
use Appwrite\Utopia\View;
use Executor\Executor;
use MaxMind\Db\Reader;
@@ -906,9 +904,6 @@ Http::init()
if (version_compare($requestFormat, '1.9.3', '<')) {
$request->addFilter(new RequestV24());
}
if (version_compare($requestFormat, '1.9.4', '<')) {
$request->addFilter(new RequestV25());
}
}
$localeParam = (string) $request->getParam('locale', $request->getHeader('x-appwrite-locale', ''));
@@ -933,9 +928,6 @@ Http::init()
*/
$responseFormat = $request->getHeader('x-appwrite-response-format', System::getEnv('_APP_SYSTEM_RESPONSE_FORMAT', ''));
if ($responseFormat) {
if (version_compare($responseFormat, '1.9.4', '<')) {
$response->addFilter(new ResponseV25());
}
if (version_compare($responseFormat, '1.9.3', '<')) {
$response->addFilter(new ResponseV24());
}
+7 -1
View File
@@ -35,6 +35,12 @@
},
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": [
{
"type": "vcs",
"url": "https://github.com/utopia-php/migration"
}
],
"require": {
"php": ">=8.3.0",
"ext-curl": "*",
@@ -74,7 +80,7 @@
"utopia-php/locale": "0.8.*",
"utopia-php/logger": "0.6.*",
"utopia-php/messaging": "0.22.*",
"utopia-php/migration": "1.9.*",
"utopia-php/migration": "dev-feat/drop-compound-resource-id#53a1426675df9c2d07e9706ed212d71c1e272294 as 1.9.7",
"utopia-php/platform": "0.13.*",
"utopia-php/pools": "1.*",
"utopia-php/span": "1.1.*",
Generated
+45 -18
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4bee36b21a57e754d2b3417e72dc9599",
"content-hash": "2fba7e6fed2dc298fcd3c77e71f7b188",
"packages": [
{
"name": "adhocore/jwt",
@@ -3850,16 +3850,16 @@
},
{
"name": "utopia-php/database",
"version": "5.4.1",
"version": "5.4.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "688d9422b5ff42ac2ecc29397d94891cfd772e93"
"reference": "a1bb3e2a4fba13032ea625b21a21039c43cffeda"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/688d9422b5ff42ac2ecc29397d94891cfd772e93",
"reference": "688d9422b5ff42ac2ecc29397d94891cfd772e93",
"url": "https://api.github.com/repos/utopia-php/database/zipball/a1bb3e2a4fba13032ea625b21a21039c43cffeda",
"reference": "a1bb3e2a4fba13032ea625b21a21039c43cffeda",
"shasum": ""
},
"require": {
@@ -3903,9 +3903,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/5.4.1"
"source": "https://github.com/utopia-php/database/tree/5.4.2"
},
"time": "2026-04-29T07:32:59+00:00"
"time": "2026-04-30T09:59:57+00:00"
},
{
"name": "utopia-php/detector",
@@ -4530,16 +4530,16 @@
},
{
"name": "utopia-php/migration",
"version": "1.9.5",
"version": "dev-feat/drop-compound-resource-id",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/migration.git",
"reference": "952a4dfe232702f80e45c35129466a8d8cb4c599"
"reference": "53a1426675df9c2d07e9706ed212d71c1e272294"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/952a4dfe232702f80e45c35129466a8d8cb4c599",
"reference": "952a4dfe232702f80e45c35129466a8d8cb4c599",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/53a1426675df9c2d07e9706ed212d71c1e272294",
"reference": "53a1426675df9c2d07e9706ed212d71c1e272294",
"shasum": ""
},
"require": {
@@ -4565,7 +4565,25 @@
"Utopia\\Migration\\": "src/Migration"
}
},
"notification-url": "https://packagist.org/downloads/",
"autoload-dev": {
"psr-4": {
"Utopia\\Tests\\": "tests/Migration"
}
},
"scripts": {
"test": [
"./vendor/bin/phpunit"
],
"lint": [
"./vendor/bin/pint --test"
],
"format": [
"./vendor/bin/pint"
],
"check": [
"./vendor/bin/phpstan analyse --level 3 src tests --memory-limit 2G"
]
},
"license": [
"MIT"
],
@@ -4578,10 +4596,10 @@
"utopia"
],
"support": {
"issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/1.9.5"
"source": "https://github.com/utopia-php/migration/tree/feat/drop-compound-resource-id",
"issues": "https://github.com/utopia-php/migration/issues"
},
"time": "2026-04-29T11:19:13+00:00"
"time": "2026-05-01T01:13:21+00:00"
},
{
"name": "utopia-php/mongo",
@@ -8442,9 +8460,18 @@
"time": "2024-11-07T12:36:22+00:00"
}
],
"aliases": [],
"aliases": [
{
"package": "utopia-php/migration",
"version": "dev-feat/drop-compound-resource-id",
"alias": "1.9.7",
"alias_normalized": "1.9.7.0"
}
],
"minimum-stability": "dev",
"stability-flags": [],
"stability-flags": {
"utopia-php/migration": 20
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
@@ -8465,5 +8492,5 @@
"platform-dev": {
"ext-fileinfo": "*"
},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}
+15 -25
View File
@@ -189,7 +189,8 @@ class Migrations extends Action
{
$source = $migration->getAttribute('source');
$destination = $migration->getAttribute('destination');
$resourceId = $this->getCompoundResourceId($migration);
$databaseId = (string) $migration->getAttribute('parentResourceId', '');
$tableId = (string) $migration->getAttribute('resourceId', '');
$credentials = $migration->getAttribute('credentials');
$migrationOptions = $migration->getAttribute('options');
/** @var Database|null $projectDB */
@@ -253,14 +254,16 @@ class Migrations extends Action
$queries
),
CSV::getName() => new CSV(
$resourceId,
$databaseId,
$tableId,
$migrationOptions['path'],
$this->deviceForMigrations,
$this->dbForProject,
$getDatabasesDB
),
JSON::getName() => new JSON(
$resourceId,
$databaseId,
$tableId,
$migrationOptions['path'],
$this->deviceForMigrations,
$this->dbForProject,
@@ -282,6 +285,8 @@ class Migrations extends Action
$destination = $migration->getAttribute('destination');
$options = $migration->getAttribute('options', []);
$credentials = $migration->getAttribute('credentials');
$databaseId = (string) $migration->getAttribute('parentResourceId', '');
$tableId = (string) $migration->getAttribute('resourceId', '');
return match ($destination) {
DestinationAppwrite::getName() => new DestinationAppwrite(
@@ -294,7 +299,8 @@ class Migrations extends Action
),
DestinationCSV::getName() => new DestinationCSV(
$this->deviceForFiles,
$this->getCompoundResourceId($migration),
$databaseId,
$tableId,
$options['bucketId'],
$options['filename'],
$options['columns'],
@@ -305,7 +311,8 @@ class Migrations extends Action
),
DestinationJSON::getName() => new DestinationJSON(
$this->deviceForFiles,
$this->getCompoundResourceId($migration),
$databaseId,
$tableId,
$options['bucketId'] ?? 'default',
$options['filename'],
$options['columns'] ?? [],
@@ -507,8 +514,9 @@ class Migrations extends Action
}
$this->updateMigrationDocument($migration, $project, $queueForRealtime);
},
$this->getCompoundResourceId($migration),
$migration->getAttribute('parentResourceType')
$migration->getAttribute('parentResourceId'),
$migration->getAttribute('parentResourceType'),
$migration->getAttribute('resourceId'),
);
$destination->shutdown();
@@ -609,24 +617,6 @@ class Migrations extends Action
return ($this->getDatabasesDB)($database);
}
/**
* Returns a "{parentResourceId}:{resourceId}" string when both are set,
* or the leaf resourceId on its own otherwise. Returning a parent-only
* value would feed the utopia-php/migration library a malformed
* compound, so an unanchored parent yields null instead.
*/
protected function getCompoundResourceId(Document $migration): ?string
{
$parentResourceId = $migration->getAttribute('parentResourceId');
$resourceId = $migration->getAttribute('resourceId');
if (!empty($parentResourceId) && !empty($resourceId)) {
return $parentResourceId . ':' . $resourceId;
}
return !empty($resourceId) ? $resourceId : null;
}
/**
* Handle actions to be performed when a CSV export migration is successfully completed
*
@@ -1,43 +0,0 @@
<?php
namespace Appwrite\Utopia\Request\Filters;
use Appwrite\Utopia\Request\Filter;
class V25 extends Filter
{
// Convert 1.9.3 params to 1.9.4
public function parse(array $content, string $model): array
{
switch ($model) {
case 'migrations.createCSVImport':
case 'migrations.createCSVExport':
case 'migrations.createJSONImport':
case 'migrations.createJSONExport':
$content = $this->parseMigrationResource($content);
break;
}
return $content;
}
protected function parseMigrationResource(array $content): array
{
if (!isset($content['resourceId']) || !\is_string($content['resourceId'])) {
return $content;
}
if (!\str_contains($content['resourceId'], ':')) {
// Leave malformed resourceId in place so the new UID validator
// surfaces it to the caller instead of silently scrubbing it.
return $content;
}
[$databaseId, $collectionId] = \explode(':', $content['resourceId'], 2);
$content['databaseId'] = $content['databaseId'] ?? $databaseId;
$content['collectionId'] = $content['collectionId'] ?? $collectionId;
unset($content['resourceId']);
return $content;
}
}
@@ -1,38 +0,0 @@
<?php
namespace Appwrite\Utopia\Response\Filters;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Filter;
// Convert 1.9.4 Data format to 1.9.3 format
class V25 extends Filter
{
public function parse(array $content, string $model): array
{
return match ($model) {
Response::MODEL_MIGRATION => $this->parseMigration($content),
Response::MODEL_MIGRATION_LIST => $this->handleList($content, 'migrations', fn ($item) => $this->parseMigration($item)),
default => $content,
};
}
protected function parseMigration(array $content): array
{
$parentResourceId = $content['parentResourceId'] ?? '';
$resourceId = $content['resourceId'] ?? '';
if ($parentResourceId !== '' && $resourceId !== '') {
$content['resourceId'] = $parentResourceId . ':' . $resourceId;
}
$content['resourceType'] = $content['parentResourceType'] ?? $content['resourceType'] ?? '';
unset($content['resourceInternalId']);
unset($content['parentResourceId']);
unset($content['parentResourceInternalId']);
unset($content['parentResourceType']);
return $content;
}
}