feat: report resources requested without their prerequisites - #226
feat: report resources requested without their prerequisites#226HarshMN2345 wants to merge 5 commits into
Conversation
A resource whose prerequisites are absent from the same request cannot be transferred. Its exporter walks a cache the missing prerequisite never filled, or is only reached by the prerequisite's own exporter, and neither path raises anything: the transfer finishes reporting success having moved none of it. Requesting membership without team is the case that reaches users, and it leaves the membership counters pending while the migration reports completed. Let a source declare what each resource needs alongside it and record an error naming whatever is absent, so the transfer fails where it used to go quiet. Sources declare nothing by default. The Appwrite source declares the pairings its exporters actually rely on. Index, collection, attribute and document are left out: they are shared between the tables, documents and vectors flavours, whose parents differ, and naming one flavour's parents would reject the others.
createProvider matched eleven provider types and fell through to a throw for Amazon SES, which both lost the provider and failed the whole migration; the SDK has had createSesProvider all along. createScheduledMessage passed null in createEmail's attachments slot, so a future-dated email arrived without its attachments even when the files had been migrated.
Assert that an incomplete request is reported and names only what is actually absent, since the untreated case is silent and a transfer that moves nothing still reports success.
Say plainly what the check is for, and cover the case where a resource is emitted by its prerequisite's exporter rather than read from the cache. Keep MockSource's properties together and mark the override.
|
| * Index, collection, attribute and document are deliberately absent. They | ||
| * are shared between the tables, documents and vectors flavours, whose | ||
| * parents differ, and naming one flavour's parents would reject the others. | ||
| * |
There was a problem hiding this comment.
Database dependencies remain incomplete
The declaration deliberately omits index, collection, attribute, and document, leaving the silent-success defect incomplete. These are requestable resources whose exporters depend on caches populated by their database or entity exporters. For example, requesting index without table or collection makes exportIndexes() iterate an empty entity cache, transfer nothing, and record no dependency error. The dependency model needs to support valid alternative parents instead of exempting these resources from validation.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/Migration/Sources/Appwrite.php
Line: 332-335
Comment:
**Database dependencies remain incomplete**
The declaration deliberately omits `index`, `collection`, `attribute`, and `document`, leaving the silent-success defect incomplete. These are requestable resources whose exporters depend on caches populated by their database or entity exporters. For example, requesting `index` without `table` or `collection` makes `exportIndexes()` iterate an empty entity cache, transfer nothing, and record no dependency error. The dependency model needs to support valid alternative parents instead of exempting these resources from validation.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| $this->source->setResourceDependencies([ | ||
| Resource::TYPE_MEMBERSHIP => [Resource::TYPE_USER, Resource::TYPE_TEAM], | ||
| ]); |
There was a problem hiding this comment.
Tests mirror dependency configuration
These tests inject the exact membership prerequisites that the production Appwrite source is supposed to declare. A typo, omission, or incorrect Appwrite declaration therefore leaves every test green; the real declaration is never exercised. This violates the repository directive to test observable behavior instead of mirroring source code or configuration in assertions. Replace this setup with coverage that consumes Appwrite's actual dependency declarations. This repository requirement must be satisfied before merging.
Context Used: Call out and harshly judge implementation-coupled ... (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/Migration/Unit/General/ResourceDependenciesTest.php
Line: 38-40
Comment:
**Tests mirror dependency configuration**
These tests inject the exact membership prerequisites that the production Appwrite source is supposed to declare. A typo, omission, or incorrect Appwrite declaration therefore leaves every test green; the real declaration is never exercised. This violates the repository directive to test observable behavior instead of mirroring source code or configuration in assertions. Replace this setup with coverage that consumes Appwrite's actual dependency declarations. This repository requirement must be satisfied before merging.
**Context Used:** Call out and harshly judge implementation-coupled ... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Why
A resource whose prerequisites are absent from the same
resourcesarray cannot be transferred, and nothing says so. The exporter walks a cache the missing prerequisite never filled, or is only reached by the prerequisite's own exporter. Either way nothing throws, so the transfer finishes reporting completed with an empty error list having moved none of it.Reproduced against real instances (Appwrite 1.9.6 source → 2.0.0 destination):
resources["user","team","membership"]errors: []["user","membership"]completed,errors: [], membership stuck atpending: 3, success: 0["team","membership"]failed,User not foundThe middle row is the problem: a migration that moved nothing reported success. This is also what let a console bug ship unnoticed — it had been omitting teams, memberships, functions and all of messaging from its requests, and every migration still came back green.
What
A source can now declare what each resource needs alongside it, and
exportResourcesrecords an error naming whatever is absent before any group runs. Sources declare nothing by default, so every other source is unaffected.The Appwrite source declares the pairings its exporters actually rely on — derived by walking every
cache->get()call site and every export gate:membershipuser,teamexportMembershipsreads both cachessubscribertopic,userexportSubscribersreads the topic cache; the importer resolves the usertabledatabaseexportEntitiesreads the database cachecolumndatabase,tableexportFieldsreads the entity cacherowdatabase,table,columnexportRecordsreads the entity and field cachesfilebucketexportFilesreads the bucket cacheenvironment-variablefunctionexportFunctionsdeploymentfunctionexportDeploymentsreads the function cachesite-variablesiteexportSitessite-deploymentsiteexportSiteDeploymentsreads the site cacheindex,collection,attributeanddocumentare deliberately absent. They are shared between the tables, documents and vectors flavours, whose parents differ, and naming one flavour's parents would reject the others.Also fixed
Two messaging defects found while tracing the above, both silent in their own way:
createProviderhad nosesarm. It matched eleven provider types and fell through todefault => throwfor Amazon SES, which lost the provider and failed the whole migration.createSesProviderhas been in the SDK all along. Credentials follow the samecredentials/optionssplit as the other email providers.createScheduledMessagepassednullintocreateEmail's attachments slot. Every future-dated email lost its attachments unconditionally, even when the buckets and files had been migrated.Testing
docker compose exec tests php vendor/bin/phpunit— 115 pass, 600 assertionscomposer lint— PASS, 106 filesphpstan --level 3 src tests— no errors