Commit Graph

9314 Commits

Author SHA1 Message Date
Jake Barnby 1b77a78121 (fix): store externalId on collection metadata, eliminate all mapping queries
- Database library: createCollection() accepts metadata parameter
  for arbitrary key-value pairs on the _metadata document
- Appwrite: passes externalId (user-facing collection ID) when
  creating collections via createCollection(metadata: ['externalId' => $collectionId])
- Metadata decorator: reads $collection->getAttribute('externalId')
  directly from the collection metadata — zero queries, zero caches,
  zero overhead
- getDatabasesDB: removed dbForProject dependency and all mapping logic

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:59:25 +13:00
Jake Barnby f66150aa8b (fix): defer event copy in UserEvents to fire-time for correct user context
The UserEvents hook copied event state at resource-resolution time
(before the init hook set the user), causing webhooks to receive null
user IDs. Now stores the source queueForEvents as a reference and
copies at fire-time when the user Document has been populated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:56:49 +13:00
Jake Barnby 5740cecbe5 (fix): pass collection to getDatabasesDB for zero-query ID mapping
Endpoints pass the collection document they already have to
getDatabasesDB. The factory registers the single collection mapping
on the Metadata decorator — no bulk find queries, no static cache,
no dbForProject dependency.

The decorator is now purely stateless with zero database overhead.
Collection ID resolution uses only the pre-registered mapping from
the endpoint's request parameters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 02:08:19 +13:00
Jake Barnby 080361338c (fix): replace deprecated Query::contains() with Query::containsAny()
Query::contains() is deprecated for array attributes in the new query
library. The deprecation warnings were spamming worker logs and
potentially slowing attribute processing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 01:23:18 +13:00
Jake Barnby 3f7261167b Merge remote-tracking branch 'origin/1.9.x' into feat-query-lib 2026-04-02 00:56:28 +13:00
Jake Barnby d7b61e6afc (fix): move collection mapping query from decorator to getDatabasesDB with static cache
The decorator no longer queries dbForProject directly. Instead,
getDatabasesDB pre-populates the mapping via setCollectionId() and
uses a static cache (Metadata::getCachedMap) so the query runs at most
ONCE per database per Swoole worker process. The decorator is now
stateless — no database dependencies, just a pre-set map.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 23:24:46 +13:00
Jake Barnby 99394e6dfa (fix): use static cache for collection mapping to avoid per-request queries
The mapping query was running once per getDatabasesDB call (once per
request). With static cache keyed by database sequence, the query runs
once per database per Swoole worker process. Subsequent requests reuse
the cached mapping. setCollectionId updates both instance and static
caches for newly created collections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 22:20:52 +13:00
Jake Barnby dc77abf161 (fix): restore Metadata decorator with lazy collection mapping, remove processDocument
Remove processDocument() and all its calls — the decorator approach is
the intended design. The Metadata decorator lazily loads the collection
ID mapping from dbForProject on first use, wrapped in silent() to
prevent lifecycle hooks. Maps both relative (collection_N) and full
(database_M_collection_N) keys to user-facing IDs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:42:00 +13:00
Jake Barnby 311ca9377b (fix): add PHPStan type annotation for collectionsCache
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 21:02:24 +13:00
Chirag Aggarwal a5b0378138 Merge pull request #11737 from appwrite/codex/phpstan-baseline-part-2
[codex] Fix PHPStan baseline cleanup issues (part 2)
2026-04-01 13:23:15 +05:30
Chirag Aggarwal 3cd90ae629 fix analyze 2026-04-01 12:59:51 +05:30
Jake Barnby 09e8380328 (fix): relax processDocument collectionsCache PHPStan type annotation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:20:15 +13:00
Jake Barnby 1eb9c386f6 (fix): replace Metadata decorator with processDocument() in endpoint actions
The Metadata decorator required a collection ID mapping query that added
overhead and caused Redis OOM in CI. Instead, stamp $databaseId and
$collectionId/$tableId directly in endpoint actions where user-facing
IDs are available from request parameters — matching the 1.9.x approach.

- Remove Metadata decorator from getDatabasesDB hooks
- Restore processDocument() on Documents/Action base class
- Add processDocument() calls in Get, Create, XList, Update, Upsert
- Simplify Metadata.php to stateless map-only decorator (no queries)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 19:58:07 +13:00
Jake Barnby 33b971a2c1 (fix): pre-compute collection mapping in getDatabasesDB, remove all queries from Metadata
Move the collection ID mapping query from the Metadata decorator to
getDatabasesDB where it runs once during resource init. The mapping
includes both relative keys (collection_N) and full keys
(database_M_collection_N) for dedicated mode compatibility.

The Metadata decorator is now purely stateless — no database queries,
no dbForProject dependency. It only uses the pre-set map from
setCollectionId().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:56:14 +13:00
Chirag Aggarwal 1788e1bd6c Address PR review feedback 2026-04-01 11:15:59 +05:30
Chirag Aggarwal 983adf3ffd Fix analyze regressions in PHPStan cleanup 2026-04-01 11:00:26 +05:30
Chirag Aggarwal f2ea0b9b48 Fix PHPStan baseline cleanup issues (part 2) 2026-04-01 10:20:20 +05:30
Jake Barnby 796179decd (fix): wrap collection mapping query in silent() to prevent hook events
The find() query on dbForProject triggers lifecycle hooks (Usage,
UserEvents, FunctionCache) that generate Redis messages, causing OOM
under CI parallel load. Wrapping in silent() prevents these hooks from
firing during the mapping query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:36:04 +13:00
Jake Barnby 21e6715bd1 (fix): remove debug logging that breaks HTTP context
Console::warning() from utopia-php/cli is not available in HTTP/Swoole
context, causing a fatal error inside the catch block and breaking the
entire decorator flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:03:15 +13:00
Damodar Lohani 28ece7de02 Change Usage class from final to non-final 2026-04-01 09:36:26 +05:45
Jake Barnby b3ed5032cf (fix): add debug logging for collection mapping failures
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:35:57 +13:00
Jake Barnby 8c6d4d8b36 Merge pull request #11734 from appwrite/fix-defaults 2026-04-01 02:50:09 +00:00
Jake Barnby 2ebc6f70ef (fix): param default 2026-04-01 15:49:40 +13:00
Damodar Lohani d9af799cc7 Merge branch '1.9.x' into claude/add-deployment-hook-method-prkpM 2026-04-01 08:09:46 +05:45
Claude b6e020389b Remove docblock from beforeCreateGitDeployment hook
https://claude.ai/code/session_01HP1N9hHbqMzxm5QmaoGhyZ
2026-04-01 02:07:36 +00:00
Jake Barnby f4cb632dbc (fix): add debug logging for collection mapping failures
Temporary debug logging to diagnose why collection ID mapping fails
in dedicated mode CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:05:03 +13:00
Jake Barnby ccc0cfbfdc (fix): migrate default 2026-04-01 15:04:52 +13:00
Claude b91506fc2d Rename hook to beforeCreateGitDeployment
https://claude.ai/code/session_01HP1N9hHbqMzxm5QmaoGhyZ
2026-04-01 02:03:59 +00:00
Claude 9ffc23946c Add validateGitDeployment hook method to Deployment trait
Add a no-op protected method that Cloud can override to enforce
billing/block checks before processing git deployments. The hook
is called inside the foreach loop after project validation, so any
exception it throws is caught and logged as an error.

https://claude.ai/code/session_01HP1N9hHbqMzxm5QmaoGhyZ
2026-04-01 02:02:18 +00:00
Jake Barnby 8bb6b5cd2a Merge pull request #11646 from appwrite/feat/import-export-json 2026-04-01 01:56:47 +00:00
Jake Barnby 7dca267727 (fix): strip database prefix from internal collection name before mapping lookup
The decorator receives full internal keys like 'database_2_collection_15'
but the mapping uses relative keys like 'collection_15'. Strip the
database prefix before looking up the mapping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:40:31 +13:00
Jake Barnby 1c19cf5323 (fix): remove silent/skipValidation from Metadata mapping query
The silent() and skipValidation() wrappers may have prevented the find
query from executing correctly. Simplified to just authorization->skip()
which is sufficient to bypass permission checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:17:55 +13:00
Jake Barnby 829cf887dc (fix): missing users case 2026-04-01 14:07:59 +13:00
Jake Barnby 124002f419 (fix): lazy-load collection mapping with silent/skipValidation to reduce Redis pressure
Move collection ID mapping query from getDatabasesDB init to lazy
loading inside the Metadata decorator. The query is wrapped in
silent() and skipValidation() to prevent triggering lifecycle hooks
(Usage, Events) that were contributing to Redis OOM in CI.

The mapping is loaded once on first need, not during resource init,
reducing overhead for requests that don't access document endpoints.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 13:19:52 +13:00
premtsd-code d862a64874 Merge branch '1.9.x' into feat/import-export-json 2026-03-31 22:54:12 +01:00
Jake Barnby dca59528df (fix): load collection ID mapping in getDatabasesDB instead of decorator
Move the collection mapping query from inside the Metadata decorator to
the getDatabasesDB resource factory. This avoids decorator-level
database queries that can fail in various contexts and cause cascading
issues.

The mapping is loaded once when getDatabasesDB creates the database
instance, and the results are passed to the Metadata decorator via
setCollectionId(). The decorator itself is now stateless with respect
to database queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 06:27:34 +13:00
Chirag Aggarwal 18ed6a9c59 Fix more PHPStan static access issues 2026-03-31 22:04:37 +05:30
Jake Barnby f8b3e687a0 (fix): batch-load collection ID mapping instead of per-document queries
Replace findOne per decoration with a single find query that loads all
collection sequence→ID mappings on first access. Caches the result for
the lifetime of the decorator instance. Silently falls back to internal
names on failure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 05:19:59 +13:00
Chirag Aggarwal 3d64ccd056 Fix more PHPStan docblock issues 2026-03-31 21:48:14 +05:30
Chirag Aggarwal 4f73eb021f Fix PHPStan core type and PHPDoc issues (part 1) 2026-03-31 21:44:20 +05:30
Jake Barnby ca99508c55 (fix): resolve internal collection names to user-facing IDs in Metadata decorator
The decorator receives _metadata documents where $id is the internal
collection name (e.g. 'collection_5'), not the user-facing collection
ID. The old processDocument() got the user-facing ID from the endpoint.

Fix: extract the sequence number from the internal name, look up the
Appwrite collection document by $sequence to get the user-facing $id,
and cache the mapping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 04:55:52 +13:00
Jake Barnby 5f4b91c350 (fix): correct ForeignKeyAction import namespace
Use Utopia\Query\Schema\ForeignKeyAction instead of the non-existent
Utopia\Database\ForeignKeyAction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 02:03:21 +13:00
Jake Barnby e8f4137249 (fix): convert onDelete string to ForeignKeyAction enum in updateRelationship
The updateRelationship() method expects ForeignKeyAction enum but
Action.php was passing the raw string from options. Use
ForeignKeyAction::from() to convert.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 01:35:13 +13:00
Jake Barnby 1b1b1dfc2b (fix): fix Metadata relatedCollection lookup, aggregate test aliases, and decorator silencing
- Metadata decorator: look for relatedCollection inside options array
  since new Attribute format nests it there
- Skip decorators during silenced operations to prevent $databaseId etc.
  from leaking into internal write operations
- Fix aggregate test queries to use Query::count('*', 'total') instead
  of Query::count('total') which treats 'total' as a column name

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:56:19 +13:00
Prem Palanisamy 4dfdfb5e59 Merge remote-tracking branch 'origin/1.9.x' into feat/import-export-json 2026-03-31 12:37:17 +01:00
Jake Barnby 7fc153d344 (fix): set project on UserEvents, stop removing $collection, update migration lib
- UserEvents hook: set project on events before triggering to fix null
  project in function worker queue messages. Also use $this->project
  directly for console check instead of $this->events->getProject()
  which was null.
- Metadata decorator: stop removing $collection from documents since
  the Response model layer already handles this in filter(). Removing it
  in the decorator broke updateDocument and cursor pagination.
- Update utopia-php/migration to feat-query-lib branch with ColumnType
  enum, Attribute objects, and removed Database::VAR_* constants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:23:09 +13:00
Jake Barnby 44d7591dd1 (fix): use ColumnType::Double for float attributes and restore databaseId response key
Float attributes must use ColumnType::Double (value 'double') to match
the existing AttributeFloat response model condition and Range validator.
ColumnType::Float (value 'float') caused "Missing model" errors and
Range validation failures.

Also reverts Collection/Table response model rule keys from $databaseId
back to databaseId since the Metadata decorator skips _metadata
documents — collection responses use the non-prefixed key.

Updates utopia-php/database with Attribute validator Float case fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 23:30:09 +13:00
Chirag Aggarwal 037878cc75 fix: use correct defaults for spec generation
Use https://appwrite.io and team@appwrite.io as defaults for _APP_HOME
and _APP_SYSTEM_TEAM_EMAIL in spec generation, instead of [HOSTNAME]
and team@localhost.test placeholders.
2026-03-31 15:11:11 +05:30
Jake Barnby 1f20a18587 (fix): update database with castingAfter fix and remove debug project filter
castingAfter must run unconditionally in createDocument to convert
adapter-specific types (MongoDB UTCDateTime) to PHP types.

Also removes hardcoded project ID check in Executions worker that was
preventing execution upserts for a specific project.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:17:26 +13:00
Jake Barnby 2cf04e4b0f (fix): skip Metadata decorator for internal documents, add Tenancy hook, fix Mongo tenant null
- Metadata decorator now skips _metadata collection documents to prevent
  injected $databaseId/$collectionId attributes from leaking into SQL
  UPDATE statements via getAttributes()
- Add Tenancy hook to dbForProject in shared mode (was missing, causing
  401 on session verification)
- Update Collection/Table response models to use $databaseId with $
  prefix matching the decorator
- Update utopia-php/database with MongoDB tenant null filter fix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 21:43:50 +13:00