Expose row bytes used/bytes free on table/collection

This commit is contained in:
Jake Barnby
2026-02-05 22:53:04 +13:00
parent cb81939604
commit 4f7337759f
9 changed files with 69 additions and 0 deletions
@@ -3,6 +3,8 @@
namespace Appwrite\Platform\Modules\Databases\Http\Databases\Collections;
use Appwrite\Extend\Exception;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Platform\Action as UtopiaAction;
use Utopia\Platform\Scope\HTTP;
@@ -165,4 +167,15 @@ abstract class Action extends UtopiaAction
? Exception::ATTRIBUTE_TYPE_INVALID
: Exception::COLUMN_TYPE_INVALID;
}
/**
* Add row bytes information to a collection/table document.
*/
protected function addRowBytesInfo(Document $document, Database $dbForProject): Document
{
$adapter = $dbForProject->getAdapter();
$document->setAttribute('bytesMax', $adapter->getDocumentSizeLimit());
$document->setAttribute('bytesUsed', $adapter->getAttributeWidth($document));
return $document;
}
}
@@ -248,6 +248,8 @@ class Create extends Action
->setParam('databaseId', $databaseId)
->setParam($this->getEventsParamKey(), $collection->getId());
$this->addRowBytesInfo($collection, $dbForProject);
$response
->setStatusCode(SwooleResponse::STATUS_CODE_CREATED)
->dynamic($collection, $this->getResponseModel());
@@ -75,6 +75,8 @@ class Get extends Action
throw new Exception($this->getNotFoundException(), params: [$collectionId]);
}
$this->addRowBytesInfo($collection, $dbForProject);
$response->dynamic($collection, $this->getResponseModel());
}
}
@@ -117,6 +117,8 @@ class Update extends Action
->setParam('databaseId', $databaseId)
->setParam($this->getEventsParamKey(), $collection->getId());
$this->addRowBytesInfo($collection, $dbForProject);
$response->dynamic($collection, $this->getResponseModel());
}
}
@@ -122,6 +122,10 @@ class XList extends Action
throw new Exception(Exception::GENERAL_QUERY_INVALID);
}
foreach ($collections as $collection) {
$this->addRowBytesInfo($collection, $dbForProject);
}
$response->dynamic(new Document([
'total' => $total,
$this->getSDKGroup() => $collections,
@@ -87,6 +87,18 @@ class Collection extends Model
'example' => new \stdClass(),
'array' => true
])
->addRule('bytesMax', [
'type' => self::TYPE_INTEGER,
'description' => 'Maximum row size in bytes. Returns 0 when no limit applies (e.g., MongoDB).',
'default' => 0,
'example' => 65535,
])
->addRule('bytesUsed', [
'type' => self::TYPE_INTEGER,
'description' => 'Currently used row size in bytes based on defined attributes.',
'default' => 0,
'example' => 1500,
])
;
}
@@ -92,6 +92,18 @@ class Table extends Model
'example' => new \stdClass(),
'array' => true
])
->addRule('bytesMax', [
'type' => self::TYPE_INTEGER,
'description' => 'Maximum row size in bytes. Returns 0 when no limit applies (e.g., MongoDB).',
'default' => 0,
'example' => 65535,
])
->addRule('bytesUsed', [
'type' => self::TYPE_INTEGER,
'description' => 'Currently used row size in bytes based on defined attributes.',
'default' => 0,
'example' => 1500,
])
;
}
@@ -62,6 +62,12 @@ trait DatabasesBase
$this->assertEquals(201, $movies['headers']['status-code']);
$this->assertEquals($movies['body']['name'], 'Movies');
$this->assertArrayHasKey('bytesMax', $movies['body']);
$this->assertArrayHasKey('bytesUsed', $movies['body']);
$this->assertIsInt($movies['body']['bytesMax']);
$this->assertIsInt($movies['body']['bytesUsed']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesMax']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesUsed']);
$actors = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
'content-type' => 'application/json',
@@ -143,6 +149,8 @@ trait DatabasesBase
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertFalse($response['body']['enabled']);
$this->assertArrayHasKey('bytesMax', $response['body']);
$this->assertArrayHasKey('bytesUsed', $response['body']);
if ($this->getSide() === 'client') {
$responseCreateDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([
@@ -363,6 +371,9 @@ trait DatabasesBase
$this->assertIsArray($movies['body']['attributes']);
$this->assertCount(9, $movies['body']['attributes']);
$this->assertArrayHasKey('bytesMax', $movies['body']);
$this->assertArrayHasKey('bytesUsed', $movies['body']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesUsed']);
$this->assertEquals($movies['body']['attributes'][0]['key'], $title['body']['key']);
$this->assertEquals($movies['body']['attributes'][1]['key'], $description['body']['key']);
$this->assertEquals($movies['body']['attributes'][2]['key'], $tagline['body']['key']);
@@ -62,6 +62,12 @@ trait DatabasesBase
$this->assertEquals(201, $movies['headers']['status-code']);
$this->assertEquals($movies['body']['name'], 'Movies');
$this->assertArrayHasKey('bytesMax', $movies['body']);
$this->assertArrayHasKey('bytesUsed', $movies['body']);
$this->assertIsInt($movies['body']['bytesMax']);
$this->assertIsInt($movies['body']['bytesUsed']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesMax']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesUsed']);
$actors = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables', array_merge([
'content-type' => 'application/json',
@@ -143,6 +149,8 @@ trait DatabasesBase
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertFalse($response['body']['enabled']);
$this->assertArrayHasKey('bytesMax', $response['body']);
$this->assertArrayHasKey('bytesUsed', $response['body']);
if ($this->getSide() === 'client') {
$responseCreateRow = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $data['moviesId'] . '/rows', array_merge([
@@ -363,6 +371,9 @@ trait DatabasesBase
$this->assertIsArray($movies['body']['columns']);
$this->assertCount(9, $movies['body']['columns']);
$this->assertArrayHasKey('bytesMax', $movies['body']);
$this->assertArrayHasKey('bytesUsed', $movies['body']);
$this->assertGreaterThanOrEqual(0, $movies['body']['bytesUsed']);
$this->assertEquals($movies['body']['columns'][0]['key'], $title['body']['key']);
$this->assertEquals($movies['body']['columns'][1]['key'], $description['body']['key']);
$this->assertEquals($movies['body']['columns'][2]['key'], $tagline['body']['key']);