mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Remove DB sleeps
This commit is contained in:
@@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Databases\Legacy;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Traits\SchemaPoll;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
@@ -16,6 +17,7 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
trait DatabasesBase
|
||||
{
|
||||
use SchemaPoll;
|
||||
public function testCreateDatabase(): array
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -64,10 +64,10 @@ class DatabasesCustomClientTest extends Scope
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
$this->waitForAttribute($databaseId, $moviesId, 'title');
|
||||
|
||||
// Document aliases write to update, delete
|
||||
$document1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $moviesId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -157,8 +157,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
]);
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to finish creating attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, 'permissionCheck', 'name');
|
||||
|
||||
// Creating document by server, give read permission to our user + some other user
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/permissionCheck/documents', array_merge([
|
||||
@@ -212,8 +211,18 @@ class DatabasesCustomClientTest extends Scope
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
|
||||
// Wait for database worker to finish deleting collection
|
||||
sleep(2);
|
||||
$start = microtime(true) * 1000;
|
||||
while ((microtime(true) * 1000) - $start < 30000) {
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
break;
|
||||
}
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
|
||||
// Make sure collection has been deleted
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/permissionCheck', array_merge([
|
||||
@@ -275,7 +284,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Collections are created synchronously, no wait needed
|
||||
|
||||
// Creating two way relationship between collection 1 and collection 2 from collection 1
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
@@ -291,7 +300,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => $collection1['body']['$id']
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collection1['body']['$id'], $collection2['body']['$id']);
|
||||
|
||||
// Update relation from collection 2 to on delete restrict
|
||||
$this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collection2['body']['$id'] . '/attributes/' . $collection1['body']['$id'] . '/relationship', array_merge([
|
||||
@@ -362,7 +371,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Collections are created synchronously, no wait needed
|
||||
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -377,11 +386,11 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertEquals('same_key', $relation['body']['twoWayKey']);
|
||||
|
||||
$this->waitForAttribute($databaseId, $collection1['body']['$id'], 'attr1');
|
||||
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -395,8 +404,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// No wait needed - request fails immediately with 409
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Attribute with the requested key \'same_key\' already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
|
||||
@@ -413,11 +421,11 @@ class DatabasesCustomClientTest extends Scope
|
||||
'key' => 'attr3',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
|
||||
$this->waitForAttribute($databaseId, $collection1['body']['$id'], 'attr3');
|
||||
|
||||
// twoWayKey is null, TwoWayKey is default, second POST
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -431,8 +439,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'key' => 'attr4',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// No wait needed - request fails immediately with 409
|
||||
$this->assertEquals('Attribute with the requested key \'attr4\' already exists. Attribute keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
|
||||
@@ -450,11 +457,11 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'playlist',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
|
||||
$this->waitForAttribute($databaseId, $collection1['body']['$id'], 'songs');
|
||||
|
||||
// Second RelationshipManyToMany on Same collections
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/attributes/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -469,8 +476,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'playlist2',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// No wait needed - request fails immediately with 409
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Creating more than one "manyToMany" relationship on the same collection is currently not permitted.', $relation['body']['message']);
|
||||
}
|
||||
@@ -674,7 +680,12 @@ class DatabasesCustomClientTest extends Scope
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $collection1['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $collection2['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $collection3['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $collection4['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $collection5['body']['$id']);
|
||||
|
||||
// Creating parent document with a child reference to test the permissions
|
||||
$parentDocument = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collection1['body']['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
||||
@@ -744,7 +744,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
]);
|
||||
$this->assertTrue($lastName['body']['encrypt']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $actors['body']['$id'], 'lastName');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -765,8 +765,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('lastName', $lastName['body']['key']);
|
||||
$this->assertEquals('string', $lastName['body']['type']);
|
||||
|
||||
// Wait for database worker to finish creating attributes
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $actors['body']['$id']);
|
||||
|
||||
// Creating document to ensure cache is purged on schema change
|
||||
$document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([
|
||||
@@ -884,8 +883,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Wait for database worker to finish creating attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $actors['body']['$id'], 'unneeded');
|
||||
|
||||
// Creating document to ensure cache is purged on schema change
|
||||
$document = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents', array_merge([
|
||||
@@ -918,8 +916,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
],
|
||||
]);
|
||||
|
||||
// Wait for database worker to finish creating index
|
||||
sleep(2);
|
||||
$this->waitForIndex($databaseId, $actors['body']['$id'], 'key_lastName');
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -947,7 +944,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $attribute['headers']['status-code']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $actors['body']['$id'], $unneededId);
|
||||
|
||||
// Check document to ensure cache is purged on schema change
|
||||
$document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([
|
||||
@@ -991,8 +988,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $index['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to finish deleting index
|
||||
sleep(2);
|
||||
$this->waitForIndexDeletion($databaseId, $data['collectionId'], $data['key']);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1036,7 +1032,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('attribute1', $attribute1['body']['key']);
|
||||
$this->assertEquals('attribute2', $attribute2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $data['collectionId']);
|
||||
|
||||
$index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1064,7 +1060,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('index1', $index1['body']['key']);
|
||||
$this->assertEquals('index2', $index2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAllIndexes($databaseId, $data['collectionId']);
|
||||
|
||||
// Expected behavior: deleting attribute2 will cause index2 to be dropped, and index1 rebuilt with a single key
|
||||
$deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['collectionId'] . '/attributes/' . $attribute2['body']['key'], array_merge([
|
||||
@@ -1075,8 +1071,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $deleted['headers']['status-code']);
|
||||
|
||||
// wait for database worker to complete
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $data['collectionId'], $attribute2['body']['key']);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['collectionId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1164,7 +1159,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('attribute1', $attribute1['body']['key']);
|
||||
$this->assertEquals('attribute2', $attribute2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
$index1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1192,7 +1187,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('index1', $index1['body']['key']);
|
||||
$this->assertEquals('index2', $index2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAllIndexes($databaseId, $collectionId);
|
||||
|
||||
// Expected behavior: deleting attribute1 would cause index1 to be a duplicate of index2 and automatically removed
|
||||
$deleted = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/' . $attribute1['body']['key'], array_merge([
|
||||
@@ -1203,8 +1198,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $deleted['headers']['status-code']);
|
||||
|
||||
// wait for database worker to complete
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $collectionId, $attribute1['body']['key']);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1353,7 +1347,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'key' => 'collection2'
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $collection1, 'collection2');
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collection2, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1361,7 +1355,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $collection1, 'collection2');
|
||||
|
||||
$attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1 . '/attributes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1422,7 +1416,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals(202, $attribute['headers']['status-code']);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
$tooWide = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1489,7 +1483,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals(202, $attribute['headers']['status-code']);
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1541,7 +1535,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals("key_attribute{$i}", $index['body']['key']);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllIndexes($databaseId, $collectionId);
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1726,7 +1720,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $attribute['headers']['status-code']);
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
return [
|
||||
'databaseId' => $databaseId,
|
||||
@@ -3745,7 +3739,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Collections are created synchronously, no wait needed
|
||||
}
|
||||
|
||||
public function cleanupRelationshipCollection(): void
|
||||
@@ -3756,7 +3750,20 @@ class DatabasesCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Poll until database is deleted (returns 404)
|
||||
$start = microtime(true) * 1000;
|
||||
$timeoutMs = 30000;
|
||||
while ((microtime(true) * 1000) - $start < $timeoutMs) {
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/database1', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]);
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
return;
|
||||
}
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public function testAttributeRenameRelationshipOneToMany()
|
||||
@@ -3780,7 +3787,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collection1Id, 'level2');
|
||||
|
||||
$collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -3894,7 +3901,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collection1Id, 'level2');
|
||||
|
||||
$collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -4008,7 +4015,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collection1Id, 'level2');
|
||||
|
||||
$collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -4126,7 +4133,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collection1Id, 'level2');
|
||||
|
||||
$collection1Attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collection1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -4274,7 +4281,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'number');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4446,7 +4453,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$data['$id']}/documents", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4512,8 +4519,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to create attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($data['databaseId'], $data['$id'], 'number');
|
||||
|
||||
// Create documents
|
||||
$createBulkDocuments = function ($amount = 10) use ($data) {
|
||||
@@ -4544,7 +4550,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
usleep(500 * 1000); // 500ms for cache purge
|
||||
|
||||
// TEST: Update all documents
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
@@ -4570,7 +4576,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
usleep(500 * 1000); // 500ms for cache purge
|
||||
|
||||
$documents = $this->client->call(Client::METHOD_GET, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4751,7 +4757,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4819,8 +4825,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to create attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($data['databaseId'], $data['$id'], 'number');
|
||||
|
||||
// Create documents
|
||||
$createBulkDocuments = function ($amount = 10) use ($data) {
|
||||
@@ -4944,7 +4949,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -5011,8 +5016,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberAttribute['headers']['status-code']);
|
||||
|
||||
// wait for database worker to create attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($data['databaseId'], $data['$id'], 'number');
|
||||
|
||||
// Create documents
|
||||
$createBulkDocuments = function ($amount = 11) use ($data) {
|
||||
@@ -5285,7 +5289,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($data['databaseId'], $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $data['databaseId'] . '/collections/' . $data['$id'] . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -5345,7 +5349,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'format' => 'datetime',
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
$date = '2000-01-01T10:00:00.000+00:00';
|
||||
|
||||
@@ -5466,7 +5470,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -5753,7 +5757,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -5984,7 +5988,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -6296,8 +6300,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $polygonAttribute['headers']['status-code']);
|
||||
|
||||
// Wait for attributes to be created
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
// Test 1: Bulk create with spatial data
|
||||
$spatialDocuments = [];
|
||||
@@ -6686,8 +6689,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
// Handle both 201 (created) and 202 (accepted) status codes
|
||||
$this->assertEquals(202, $lineAttribute['headers']['status-code']);
|
||||
|
||||
// Wait for attributes to be created
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $collectionId);
|
||||
|
||||
// Test bulk create with line string data
|
||||
$lineStringDocuments = [];
|
||||
|
||||
@@ -6,6 +6,7 @@ use Tests\E2E\Client;
|
||||
use Tests\E2E\Scopes\ProjectCustom;
|
||||
use Tests\E2E\Scopes\Scope;
|
||||
use Tests\E2E\Scopes\SideClient;
|
||||
use Tests\E2E\Traits\SchemaPoll;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
@@ -15,6 +16,7 @@ class ACIDTest extends Scope
|
||||
{
|
||||
use ProjectCustom;
|
||||
use SideClient;
|
||||
use SchemaPoll;
|
||||
|
||||
/**
|
||||
* Test atomicity - all operations succeed or all fail
|
||||
@@ -73,7 +75,8 @@ class ACIDTest extends Scope
|
||||
'attributes' => ['email']
|
||||
]);
|
||||
|
||||
sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'email');
|
||||
$this->waitForIndex($databaseId, $collectionId, 'unique_email');
|
||||
|
||||
// Create first document outside transaction
|
||||
$doc1 = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([
|
||||
@@ -229,7 +232,7 @@ class ACIDTest extends Scope
|
||||
'max' => 100
|
||||
]);
|
||||
|
||||
sleep(3);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'age');
|
||||
|
||||
// Create transaction
|
||||
$transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([
|
||||
@@ -350,7 +353,7 @@ class ACIDTest extends Scope
|
||||
'max' => 1000000
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'counter');
|
||||
|
||||
// Create initial document with counter
|
||||
$doc = $this->client->call(Client::METHOD_POST, "/databases/{$databaseId}/collections/{$collectionId}/documents", array_merge([
|
||||
@@ -507,7 +510,7 @@ class ACIDTest extends Scope
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $collectionId, 'data');
|
||||
|
||||
// Create and commit transaction with multiple operations
|
||||
$transaction = $this->client->call(Client::METHOD_POST, '/databases/transactions', array_merge([
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests\E2E\Services\Databases\TablesDB;
|
||||
|
||||
use Appwrite\Extend\Exception;
|
||||
use Tests\E2E\Client;
|
||||
use Tests\E2E\Traits\SchemaPoll;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
@@ -16,6 +17,20 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
trait DatabasesBase
|
||||
{
|
||||
use SchemaPoll;
|
||||
|
||||
/**
|
||||
* Override API config for TablesDB endpoints
|
||||
*/
|
||||
protected function getSchemaApiConfig(): array
|
||||
{
|
||||
return [
|
||||
'basePath' => '/tablesdb',
|
||||
'collectionPath' => 'tables',
|
||||
'attributePath' => 'columns',
|
||||
'indexPath' => 'indexes',
|
||||
];
|
||||
}
|
||||
public function testCreateDatabase(): array
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -64,10 +64,10 @@ class DatabasesCustomClientTest extends Scope
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
$this->waitForAttribute($databaseId, $moviesId, 'title');
|
||||
|
||||
// Document aliases write to update, delete
|
||||
$row1 = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $moviesId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -157,8 +157,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
]);
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to finish creating attributes
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, 'permissionCheck', 'name');
|
||||
|
||||
// Creating row by server, give read permission to our user + some other user
|
||||
$response = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/permissionCheck/rows', array_merge([
|
||||
@@ -212,8 +211,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
|
||||
// Wait for database worker to finish deleting table
|
||||
sleep(2);
|
||||
usleep(500 * 1000);
|
||||
|
||||
// Make sure table has been deleted
|
||||
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/permissionCheck', array_merge([
|
||||
@@ -275,8 +273,6 @@ class DatabasesCustomClientTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// Creating two way relationship between table 1 and table 2 from table 1
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -291,7 +287,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => $table1['body']['$id']
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $table1['body']['$id'], $table2['body']['$id']);
|
||||
|
||||
// Update relation from table 2 to on delete restrict
|
||||
$this->client->call(Client::METHOD_PATCH, '/tablesdb/' . $databaseId . '/tables/' . $table2['body']['$id'] . '/columns/' . $table1['body']['$id'] . '/relationship', array_merge([
|
||||
@@ -362,8 +358,6 @@ class DatabasesCustomClientTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
$relation = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/columns/relationship', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
@@ -377,7 +371,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
$this->waitForAttribute($databaseId, $table1['body']['$id'], 'attr1');
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertEquals('same_key', $relation['body']['twoWayKey']);
|
||||
@@ -395,8 +389,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'same_key'
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// This request fails with 409 - no need to wait
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Column with the requested key \'same_key\' already exists. Column keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
|
||||
@@ -413,7 +406,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'key' => 'attr3',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
$this->waitForAttribute($databaseId, $table1['body']['$id'], 'attr3');
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
@@ -431,8 +424,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'key' => 'attr4',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// This request fails with 409 - no need to wait
|
||||
$this->assertEquals('Column with the requested key \'attr4\' already exists. Column keys must be unique, try again with a different key.', $relation['body']['message']);
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
|
||||
@@ -450,7 +442,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'playlist',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
$this->waitForAttribute($databaseId, $table1['body']['$id'], 'songs');
|
||||
|
||||
$this->assertEquals(202, $relation['headers']['status-code']);
|
||||
$this->assertArrayHasKey('twoWayKey', $relation['body']);
|
||||
@@ -469,8 +461,7 @@ class DatabasesCustomClientTest extends Scope
|
||||
'twoWayKey' => 'playlist2',
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
|
||||
// This request fails with 409 - no need to wait
|
||||
$this->assertEquals(409, $relation['body']['code']);
|
||||
$this->assertEquals('Creating more than one "manyToMany" relationship on the same table is currently not permitted.', $relation['body']['message']);
|
||||
}
|
||||
@@ -674,7 +665,12 @@ class DatabasesCustomClientTest extends Scope
|
||||
'default' => null,
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $table1['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $table2['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $table3['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $table4['body']['$id']);
|
||||
$this->waitForAllAttributes($databaseId, $table5['body']['$id']);
|
||||
|
||||
// Creating parent row with a child reference to test the permissions
|
||||
$parentDocument = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $table1['body']['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
|
||||
@@ -727,8 +727,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('lastName', $lastName['body']['key']);
|
||||
$this->assertEquals('string', $lastName['body']['type']);
|
||||
|
||||
// Wait for database worker to finish creating columns
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $actors['body']['$id']);
|
||||
|
||||
// Creating row to ensure cache is purged on schema change
|
||||
$row = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([
|
||||
@@ -828,8 +827,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Wait for database worker to finish creating columns
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $actors['body']['$id'], 'unneeded');
|
||||
|
||||
// Creating row to ensure cache is purged on schema change
|
||||
$row = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows', array_merge([
|
||||
@@ -862,8 +860,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
],
|
||||
]);
|
||||
|
||||
// Wait for database worker to finish creating index
|
||||
sleep(2);
|
||||
$this->waitForIndex($databaseId, $actors['body']['$id'], 'key_lastName');
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $actors['body']['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -891,7 +888,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $column['headers']['status-code']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $actors['body']['$id'], $unneededId);
|
||||
|
||||
// Check row to ensure cache is purged on schema change
|
||||
$row = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $actors['body']['$id'] . '/rows/' . $row['body']['$id'], array_merge([
|
||||
@@ -935,8 +932,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $index['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to finish deleting index
|
||||
sleep(2);
|
||||
$this->waitForIndexDeletion($databaseId, $data['tableId'], $data['key']);
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $data['tableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -980,7 +976,8 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('column1', $column1['body']['key']);
|
||||
$this->assertEquals('column2', $column2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $data['tableId'], 'column1');
|
||||
$this->waitForAttribute($databaseId, $data['tableId'], 'column2');
|
||||
|
||||
$index1 = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $data['tableId'] . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1008,7 +1005,8 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('index1', $index1['body']['key']);
|
||||
$this->assertEquals('index2', $index2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForIndex($databaseId, $data['tableId'], 'index1');
|
||||
$this->waitForIndex($databaseId, $data['tableId'], 'index2');
|
||||
|
||||
// Expected behavior: deleting column2 will cause index2 to be dropped, and index1 rebuilt with a single key
|
||||
$deleted = $this->client->call(Client::METHOD_DELETE, '/tablesdb/' . $databaseId . '/tables/' . $data['tableId'] . '/columns/' . $column2['body']['key'], array_merge([
|
||||
@@ -1019,8 +1017,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $deleted['headers']['status-code']);
|
||||
|
||||
// wait for database worker to complete
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $data['tableId'], 'column2');
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $data['tableId'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1108,7 +1105,8 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('column1', $column1['body']['key']);
|
||||
$this->assertEquals('column2', $column2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $tableId, 'column1');
|
||||
$this->waitForAttribute($databaseId, $tableId, 'column2');
|
||||
|
||||
$index1 = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/indexes', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1136,7 +1134,8 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals('index1', $index1['body']['key']);
|
||||
$this->assertEquals('index2', $index2['body']['key']);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForIndex($databaseId, $tableId, 'index1');
|
||||
$this->waitForIndex($databaseId, $tableId, 'index2');
|
||||
|
||||
// Expected behavior: deleting column1 would cause index1 to be a duplicate of index2 and automatically removed
|
||||
$deleted = $this->client->call(Client::METHOD_DELETE, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/' . $column1['body']['key'], array_merge([
|
||||
@@ -1147,8 +1146,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(204, $deleted['headers']['status-code']);
|
||||
|
||||
// wait for database worker to complete
|
||||
sleep(2);
|
||||
$this->waitForAttributeDeletion($databaseId, $tableId, 'column1');
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1297,7 +1295,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'key' => 'table2'
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $table1, 'table2');
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/tablesdb/' . $databaseId . '/tables/' . $table2, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1305,7 +1303,18 @@ class DatabasesCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
sleep(2);
|
||||
$start = microtime(true) * 1000;
|
||||
while ((microtime(true) * 1000) - $start < 30000) {
|
||||
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table2, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]));
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
break;
|
||||
}
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
|
||||
$columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table1 . '/columns', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1366,7 +1375,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals(202, $column['headers']['status-code']);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
$tooWide = $this->client->call(Client::METHOD_POST, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1433,7 +1442,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals(202, $column['headers']['status-code']);
|
||||
}
|
||||
|
||||
sleep(10);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1470,7 +1479,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
$this->assertEquals("key_column{$i}", $index['body']['key']);
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllIndexes($databaseId, $tableId);
|
||||
|
||||
$table = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -1655,7 +1664,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $column['headers']['status-code']);
|
||||
|
||||
sleep(5);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
return [
|
||||
'databaseId' => $databaseId,
|
||||
@@ -3674,7 +3683,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
]
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Tables are created synchronously, no wait needed
|
||||
}
|
||||
|
||||
public function cleanupRelationshipTable(): void
|
||||
@@ -3685,7 +3694,20 @@ class DatabasesCustomServerTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]);
|
||||
|
||||
\sleep(2);
|
||||
// Poll until database is deleted (returns 404)
|
||||
$start = microtime(true) * 1000;
|
||||
$timeoutMs = 30000;
|
||||
while ((microtime(true) * 1000) - $start < $timeoutMs) {
|
||||
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/database1', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]);
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
return;
|
||||
}
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public function testColumnRenameRelationshipOneToMany()
|
||||
@@ -3709,7 +3731,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $table1Id, 'level2');
|
||||
|
||||
$table1Columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -3823,7 +3845,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $table1Id, 'level2');
|
||||
|
||||
$table1Columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -3937,7 +3959,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $table1Id, 'level2');
|
||||
|
||||
$table1Columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -4055,7 +4077,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'twoWayKey' => 'level1'
|
||||
]);
|
||||
|
||||
\sleep(3);
|
||||
$this->waitForAttribute($databaseId, $table1Id, 'level2');
|
||||
|
||||
$table1Columns = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $table1Id, [
|
||||
'content-type' => 'application/json',
|
||||
@@ -4203,7 +4225,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberColumn['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'number');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$data['$id']}/rows", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4375,7 +4397,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_POST, "/tablesdb/{$databaseId}/tables/{$data['$id']}/rows", array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4441,8 +4463,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberColumn['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to create columns
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'number');
|
||||
|
||||
// Create rows
|
||||
$createBulkRows = function ($amount = 10) use ($data) {
|
||||
@@ -4473,7 +4494,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
usleep(500 * 1000);
|
||||
|
||||
// TEST: Update all rows
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/tablesdb/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
@@ -4499,7 +4520,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
* This test specifically failed on 1.6.x response format,
|
||||
* could be due to the slow or overworked machine, but being safe here!
|
||||
*/
|
||||
sleep(5);
|
||||
usleep(500 * 1000);
|
||||
|
||||
$rows = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4663,7 +4684,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/tablesdb/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4731,8 +4752,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberColumn['headers']['status-code']);
|
||||
|
||||
// Wait for database worker to create columns
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'number');
|
||||
|
||||
// Create rows
|
||||
$createBulkRows = function ($amount = 10) use ($data) {
|
||||
@@ -4856,7 +4876,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/tablesdb/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -4923,8 +4943,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $numberColumn['headers']['status-code']);
|
||||
|
||||
// wait for database worker to create columns
|
||||
sleep(2);
|
||||
$this->waitForAttribute($databaseId, $data['$id'], 'number');
|
||||
|
||||
// Create rows
|
||||
$createBulkRows = function ($amount = 11) use ($data) {
|
||||
@@ -5197,7 +5216,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($data['databaseId'], $data['$id'], 'level2');
|
||||
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/tablesdb/' . $data['databaseId'] . '/tables/' . $data['$id'] . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
@@ -5257,7 +5276,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'format' => 'datetime',
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
$date = '2000-01-01T10:00:00.000+00:00';
|
||||
|
||||
@@ -5378,7 +5397,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $tableId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -5665,7 +5684,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $tableId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -5910,7 +5929,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
$this->waitForAttribute($databaseId, $tableId, 'string');
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
@@ -6222,8 +6241,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
|
||||
$this->assertEquals(202, $polygonColumn['headers']['status-code']);
|
||||
|
||||
// Wait for columns to be created
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
// Test 1: Bulk create with spatial data
|
||||
$spatialRows = [];
|
||||
@@ -6620,8 +6638,7 @@ class DatabasesCustomServerTest extends Scope
|
||||
// Handle both 201 (created) and 202 (accepted) status codes
|
||||
$this->assertEquals(202, $lineColumn['headers']['status-code']);
|
||||
|
||||
// Wait for columns to be created
|
||||
sleep(2);
|
||||
$this->waitForAllAttributes($databaseId, $tableId);
|
||||
|
||||
// Test bulk create with line string data
|
||||
$lineStringRows = [];
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\E2E\Traits;
|
||||
|
||||
use Tests\E2E\Client;
|
||||
|
||||
trait SchemaPoll
|
||||
{
|
||||
protected function getSchemaApiConfig(): array
|
||||
{
|
||||
return [
|
||||
'basePath' => '/databases',
|
||||
'collectionPath' => 'collections',
|
||||
'attributePath' => 'attributes',
|
||||
'indexPath' => 'indexes',
|
||||
];
|
||||
}
|
||||
|
||||
protected function waitForAttribute(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
string $attributeKey,
|
||||
int $timeoutMs = 30000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId, $attributeKey) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['attributePath'] . '/' . $attributeKey,
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
$status = $response['body']['status'] ?? 'unknown';
|
||||
|
||||
if ($status === 'failed') {
|
||||
throw new \Exception("Attribute creation failed: " . ($response['body']['error'] ?? 'unknown error'));
|
||||
}
|
||||
|
||||
$this->assertEquals('available', $status);
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
|
||||
protected function waitForIndex(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
string $indexKey,
|
||||
int $timeoutMs = 60000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId, $indexKey) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['indexPath'] . '/' . $indexKey,
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
$status = $response['body']['status'] ?? 'unknown';
|
||||
|
||||
if ($status === 'failed') {
|
||||
throw new \Exception("Index creation failed: " . ($response['body']['error'] ?? 'unknown error'));
|
||||
}
|
||||
|
||||
$this->assertEquals('available', $status);
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
|
||||
protected function waitForAllAttributes(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
int $timeoutMs = 30000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['attributePath'],
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
$attributes = $response['body']['attributes'] ?? $response['body']['columns'] ?? [];
|
||||
|
||||
if (empty($attributes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($attributes as $attr) {
|
||||
if ($attr['status'] === 'failed') {
|
||||
throw new \Exception("Attribute '{$attr['key']}' creation failed: " . ($attr['error'] ?? 'unknown error'));
|
||||
}
|
||||
$this->assertEquals('available', $attr['status']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
|
||||
protected function waitForAllIndexes(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
int $timeoutMs = 60000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['indexPath'],
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
$indexes = $response['body']['indexes'] ?? [];
|
||||
|
||||
if (empty($indexes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($indexes as $index) {
|
||||
if ($index['status'] === 'failed') {
|
||||
throw new \Exception("Index '{$index['key']}' creation failed: " . ($index['error'] ?? 'unknown error'));
|
||||
}
|
||||
$this->assertEquals('available', $index['status']);
|
||||
}
|
||||
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
|
||||
protected function waitForAttributeDeletion(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
string $attributeKey,
|
||||
int $timeoutMs = 30000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId, $attributeKey) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['attributePath'] . '/' . $attributeKey,
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$status = $response['body']['status'] ?? 'unknown';
|
||||
|
||||
if ($status === 'available') {
|
||||
throw new \Exception("Attribute '{$attributeKey}' deletion failed - still available");
|
||||
}
|
||||
|
||||
$this->assertNotEquals('deleting', $status);
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
|
||||
protected function waitForIndexDeletion(
|
||||
string $databaseId,
|
||||
string $collectionId,
|
||||
string $indexKey,
|
||||
int $timeoutMs = 60000,
|
||||
int $intervalMs = 100
|
||||
): void {
|
||||
$config = $this->getSchemaApiConfig();
|
||||
|
||||
$this->assertEventually(function () use ($config, $databaseId, $collectionId, $indexKey) {
|
||||
$response = $this->client->call(
|
||||
Client::METHOD_GET,
|
||||
$config['basePath'] . '/' . $databaseId . '/' . $config['collectionPath'] . '/' . $collectionId . '/' . $config['indexPath'] . '/' . $indexKey,
|
||||
array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders())
|
||||
);
|
||||
|
||||
if ($response['headers']['status-code'] === 404) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$status = $response['body']['status'] ?? 'unknown';
|
||||
|
||||
if ($status === 'available') {
|
||||
throw new \Exception("Index '{$indexKey}' deletion failed - still available");
|
||||
}
|
||||
|
||||
$this->assertNotEquals('deleting', $status);
|
||||
return true;
|
||||
}, $timeoutMs, $intervalMs);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user