Skip to content

feat(appwrite): create the abuse table schema inline - #120

Merged
abnegate merged 2 commits into
mainfrom
feat/inline-tablesdb-schema
Aug 11, 2026
Merged

feat(appwrite): create the abuse table schema inline#120
abnegate merged 2 commits into
mainfrom
feat/inline-tablesdb-schema

Conversation

@claudear

@claudear claudear commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What

appwrite/appwrite#13174 moved the attribute type/format/size mapping into Appwrite\Utopia\Database\Attribute, shared by the inline validator and the inline attribute builder. The PR calls out the cost of the old behaviour directly: callers hit a partially-executed request and "have to fall back to createTable + N separate column calls". That fallback is exactly what this adapter did.

setup() now sends the whole schema — three columns and two indexes — inline with createTable, in one request. Inline columns and indexes are created synchronously and land as available, so the two waitForResourcesReady() polling loops are gone from the cold path. Setting up the abuse table drops from 6 requests plus up to 30s of polling to 2 requests.

The dedicated per-column endpoints are still needed for one case: a table left behind by a setup() that did not run to completion. Inline definitions only apply while the table is being created, so when createTable reports table_already_exists the adapter falls back to the old incremental path (which is what makes a partial setup self-heal today). createColumns()/createIndexes() now read that schema from columnDefinitions()/indexDefinitions() rather than restating it, so the two paths cannot drift.

executeWithSilentError() returns whether the call went through, which is how setup() distinguishes the two cases.

Also in here

  • appwrite/appwrite 26.0 → 27.1. Every SDK method this adapter uses (createTable, create*Column, createIndex, listColumns, listIndexes, listRows, createRow, updateRow, incrementRowColumn, deleteRows) has an identical signature in 27.1; the 27.x changes are additive (dedicated database specifications, replicas, vector queries). Note the fix itself is server-side and needs no SDK change.
  • Readiness poll fix. ColumnIndexList hydrates each entry into a ColumnIndex, but ColumnList hands back the raw payloads — the SDK has no single model to hydrate the union of column types into. (string) $resource->status on an array therefore yielded '', never 'available', so once a column really was still processing the loop could only ever run out of attempts and throw. resourceStatus() reads the status off either shape.

Tests

tests/Abuse/Appwrite/TablesDBTest.php:

  • testSetupCreatesSchema — asserts the inline path produces the same columns and indexes the dedicated endpoints did: key string(255) required, time datetime required, count integer required with min 0 / max PHP_INT_MAX, a unique index over key, time and a key index over time, all available.
  • testSetupRepairsPartiallyCreatedTable — creates a bare table to stand in for a setup that died halfway, runs setup(), and asserts the fallback fills in every column and index and that rate limiting then works through the repaired table.
  • testSetupIsIdempotentsetup() runs on every boot, so a second call must not duplicate or re-create anything.

Green on 8.4 and 8.5 against the CI Appwrite endpoint, along with Pint, PHPStan (level max) and the benchmarks. The first push failed these three tests for the hydration reason above, which is what turned up the asymmetry between the two list endpoints; the second run needed one retry after a TLS reset mid-request on 8.5.

🤖 Generated with Claude Code

Appwrite now builds columns and indexes sent inline with create table from
the same mapping the dedicated per-column endpoints use, so the workaround
of create table + one request per column is no longer needed
(appwrite/appwrite#13174).

Setup now sends the whole schema with the table in a single request. Inline
columns and indexes come back available, so the two polling loops are gone
from the cold path. A table left over from a setup that did not run to
completion still falls back to the per-column endpoints, since inline
definitions only apply while the table is being created; both paths now read
the schema from one list instead of restating it.

Also bumps appwrite/appwrite to 27.1, and fixes the readiness poll: list
responses carry raw payloads rather than hydrated models, so reading status
as a property always yielded '' and the poll could only ever time out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown

Greptile Summary

The PR creates the Appwrite abuse-table schema inline while retaining incremental repair for existing partial tables.

  • Centralizes column and index definitions for both creation paths.
  • Corrects readiness-status extraction for raw arrays and hydrated models.
  • Updates the Appwrite PHP SDK from 26.0 to 27.1 and expands integration coverage.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/Abuse/Adapters/TimeLimit/Appwrite/TablesDB.php Creates columns and indexes inline, preserves repair behavior for existing tables, and handles both array and object resource statuses.
tests/Abuse/Appwrite/TablesDBTest.php Adds integration coverage for inline schema creation, partial-table repair, and idempotent setup.
composer.json Raises the Appwrite PHP SDK requirement from 26.0 to 27.1.
composer.lock Locks Appwrite SDK 27.1.0 and its new JWT dependency.

Reviews (2): Last reviewed commit: "fix(tests): read listed indexes as model..." | Re-trigger Greptile

listIndexes hydrates each entry into a ColumnIndex; listColumns does not,
because the SDK has no single model for the union of column types. The
schema assertions treated both as arrays.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@abnegate
abnegate merged commit 0f0d16d into main Aug 11, 2026
7 of 8 checks passed
@abnegate
abnegate deleted the feat/inline-tablesdb-schema branch August 11, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants