diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index c8903538d0..6d71855a5a 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1,6 +1,7 @@ $collection->getInternalId(), 'collectionId' => $collectionId, 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck + 'status' => Status::CREATING, 'size' => $size, 'required' => $required, 'signed' => $signed, @@ -173,7 +174,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att 'collectionInternalId' => $relatedCollection->getInternalId(), 'collectionId' => $relatedCollection->getId(), 'type' => $type, - 'status' => 'processing', // processing, available, failed, deleting, stuck + 'status' => Status::CREATING, 'size' => $size, 'required' => $required, 'signed' => $signed, @@ -254,7 +255,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } - if ($attribute->getAttribute('status') !== 'available') { + if ($attribute->getAttribute('status') !== Status::AVAILABLE) { throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE); } @@ -2306,8 +2307,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key } // Only update status if removing available attribute - if ($attribute->getAttribute('status') === 'available') { - $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); + if ($attribute->getAttribute('status') === Status::AVAILABLE) { + $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', Status::DELETING)); } $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); @@ -2328,8 +2329,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } - if ($relatedAttribute->getAttribute('status') === 'available') { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); + if ($relatedAttribute->getAttribute('status') === Status::AVAILABLE) { + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', Status::DELETING)); } $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $options['relatedCollection']); @@ -2430,7 +2431,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $oldAttributes[] = [ 'key' => '$id', 'type' => Database::VAR_STRING, - 'status' => 'available', + 'status' => Status::AVAILABLE, 'required' => true, 'array' => false, 'default' => null, @@ -2440,7 +2441,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $oldAttributes[] = [ 'key' => '$createdAt', 'type' => Database::VAR_DATETIME, - 'status' => 'available', + 'status' => Status::AVAILABLE, 'signed' => false, 'required' => false, 'array' => false, @@ -2451,7 +2452,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $oldAttributes[] = [ 'key' => '$updatedAt', 'type' => Database::VAR_DATETIME, - 'status' => 'available', + 'status' => Status::AVAILABLE, 'signed' => false, 'required' => false, 'array' => false, @@ -2480,7 +2481,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } // ensure attribute is available - if ($attributeStatus !== 'available') { + if ($attributeStatus !== Status::AVAILABLE) { throw new Exception(Exception::ATTRIBUTE_NOT_AVAILABLE, 'Attribute not available: ' . $oldAttributes[$attributeIndex]['key']); } @@ -2499,7 +2500,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $index = new Document([ '$id' => ID::custom($db->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, - 'status' => 'processing', // processing, available, failed, deleting, stuck + 'status' => Status::CREATING, 'databaseInternalId' => $db->getInternalId(), 'databaseId' => $databaseId, 'collectionInternalId' => $collection->getInternalId(), @@ -2694,8 +2695,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') } // Only update status if removing available index - if ($index->getAttribute('status') === 'available') { - $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); + if ($index->getAttribute('status') === Status::AVAILABLE) { + $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', Status::DELETING)); } $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); diff --git a/src/Appwrite/Database/Status.php b/src/Appwrite/Database/Status.php new file mode 100644 index 0000000000..78c05221fc --- /dev/null +++ b/src/Appwrite/Database/Status.php @@ -0,0 +1,13 @@ +getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', Status::AVAILABLE)); } break; default: @@ -169,7 +170,7 @@ class Databases extends Action } } - $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); + $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', Status::AVAILABLE)); } catch (\Throwable $e) { // TODO: Send non DatabaseExceptions to Sentry Console::error($e->getMessage()); @@ -184,14 +185,14 @@ class Databases extends Action $dbForProject->updateDocument( 'attributes', $attribute->getId(), - $attribute->setAttribute('status', 'failed') + $attribute->setAttribute('status', Status::FAILED) ); if (isset($relatedAttribute)) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), - $relatedAttribute->setAttribute('status', 'failed') + $relatedAttribute->setAttribute('status', Status::FAILED) ); } } finally { @@ -249,7 +250,7 @@ class Databases extends Action // - stuck: attribute was available but cannot be removed try { - if ($status !== 'failed') { + if ($status !== Status::FAILED) { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); @@ -260,7 +261,7 @@ class Databases extends Action } if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { - $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); + $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', Status::FAILED)); throw new DatabaseException('Failed to delete Relationship'); } } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { @@ -286,13 +287,13 @@ class Databases extends Action $dbForProject->updateDocument( 'attributes', $attribute->getId(), - $attribute->setAttribute('status', 'stuck') + $attribute->setAttribute('status', Status::FAILED) ); if (!$relatedAttribute->isEmpty()) { $dbForProject->updateDocument( 'attributes', $relatedAttribute->getId(), - $relatedAttribute->setAttribute('status', 'stuck') + $relatedAttribute->setAttribute('status', Status::FAILED) ); } } finally { @@ -400,7 +401,7 @@ class Databases extends Action if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } - $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); + $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', Status::AVAILABLE)); } catch (\Throwable $e) { // TODO: Send non DatabaseExceptions to Sentry Console::error($e->getMessage()); @@ -411,7 +412,7 @@ class Databases extends Action $dbForProject->updateDocument( 'indexes', $index->getId(), - $index->setAttribute('status', 'failed') + $index->setAttribute('status', Status::FAILED) ); } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); @@ -454,7 +455,7 @@ class Databases extends Action $project = $dbForConsole->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if ($status !== Status::FAILED && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -469,7 +470,7 @@ class Databases extends Action $dbForProject->updateDocument( 'indexes', $index->getId(), - $index->setAttribute('status', 'stuck') + $index->setAttribute('status', Status::FAILED) ); } finally { $this->trigger($database, $collection, $index, $project, $projectId, $events); diff --git a/src/Appwrite/Utopia/Response/Model/Attribute.php b/src/Appwrite/Utopia/Response/Model/Attribute.php index 9f9ceca317..c4af2e7b1a 100644 --- a/src/Appwrite/Utopia/Response/Model/Attribute.php +++ b/src/Appwrite/Utopia/Response/Model/Attribute.php @@ -2,6 +2,7 @@ namespace Appwrite\Utopia\Response\Model; +use Appwrite\Database\Status; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; @@ -24,9 +25,9 @@ class Attribute extends Model ]) ->addRule('status', [ 'type' => self::TYPE_STRING, - 'description' => 'Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', + 'description' => 'Attribute status. Possible values: `'.Status::QUEUED.'`,`'.Status::CREATING.'`,`'.Status::DELETING.'`,`'.Status::AVAILABLE.'`, , or `'.Status::FAILED.'`', 'default' => '', - 'example' => 'available', + 'example' => Status::AVAILABLE, ]) ->addRule('error', [ 'type' => self::TYPE_STRING, diff --git a/src/Appwrite/Utopia/Response/Model/Index.php b/src/Appwrite/Utopia/Response/Model/Index.php index 3d3d1a3b52..b1d1843ae8 100644 --- a/src/Appwrite/Utopia/Response/Model/Index.php +++ b/src/Appwrite/Utopia/Response/Model/Index.php @@ -2,6 +2,7 @@ namespace Appwrite\Utopia\Response\Model; +use Appwrite\Database\Status; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; @@ -24,7 +25,7 @@ class Index extends Model ]) ->addRule('status', [ 'type' => self::TYPE_STRING, - 'description' => 'Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`', + 'description' => 'Index status. Possible values: `'.Status::QUEUED.'`,`'.Status::CREATING.'`,`'.Status::DELETING.'`,`'.Status::AVAILABLE.'`, , or `'.Status::FAILED.'`', 'default' => '', 'example' => 'available', ]) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 6f65552f1c..2f6c730e36 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Databases; +use Appwrite\Database\Status; use Appwrite\Extend\Exception; use Tests\E2E\Client; use Utopia\Database\Database; @@ -789,7 +790,7 @@ trait DatabasesBase $this->assertEquals(200, $stringResponse['headers']['status-code']); $this->assertEquals($string['body']['key'], $stringResponse['body']['key']); $this->assertEquals($string['body']['type'], $stringResponse['body']['type']); - $this->assertEquals('available', $stringResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $stringResponse['body']['status']); $this->assertEquals($string['body']['required'], $stringResponse['body']['required']); $this->assertEquals($string['body']['array'], $stringResponse['body']['array']); $this->assertEquals(16, $stringResponse['body']['size']); @@ -798,7 +799,7 @@ trait DatabasesBase $this->assertEquals(200, $emailResponse['headers']['status-code']); $this->assertEquals($email['body']['key'], $emailResponse['body']['key']); $this->assertEquals($email['body']['type'], $emailResponse['body']['type']); - $this->assertEquals('available', $emailResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $emailResponse['body']['status']); $this->assertEquals($email['body']['required'], $emailResponse['body']['required']); $this->assertEquals($email['body']['array'], $emailResponse['body']['array']); $this->assertEquals($email['body']['format'], $emailResponse['body']['format']); @@ -807,7 +808,7 @@ trait DatabasesBase $this->assertEquals(200, $enumResponse['headers']['status-code']); $this->assertEquals($enum['body']['key'], $enumResponse['body']['key']); $this->assertEquals($enum['body']['type'], $enumResponse['body']['type']); - $this->assertEquals('available', $enumResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $enumResponse['body']['status']); $this->assertEquals($enum['body']['required'], $enumResponse['body']['required']); $this->assertEquals($enum['body']['array'], $enumResponse['body']['array']); $this->assertEquals($enum['body']['format'], $enumResponse['body']['format']); @@ -817,7 +818,7 @@ trait DatabasesBase $this->assertEquals(200, $ipResponse['headers']['status-code']); $this->assertEquals($ip['body']['key'], $ipResponse['body']['key']); $this->assertEquals($ip['body']['type'], $ipResponse['body']['type']); - $this->assertEquals('available', $ipResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $ipResponse['body']['status']); $this->assertEquals($ip['body']['required'], $ipResponse['body']['required']); $this->assertEquals($ip['body']['array'], $ipResponse['body']['array']); $this->assertEquals($ip['body']['format'], $ipResponse['body']['format']); @@ -826,7 +827,7 @@ trait DatabasesBase $this->assertEquals(200, $urlResponse['headers']['status-code']); $this->assertEquals($url['body']['key'], $urlResponse['body']['key']); $this->assertEquals($url['body']['type'], $urlResponse['body']['type']); - $this->assertEquals('available', $urlResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $urlResponse['body']['status']); $this->assertEquals($url['body']['required'], $urlResponse['body']['required']); $this->assertEquals($url['body']['array'], $urlResponse['body']['array']); $this->assertEquals($url['body']['format'], $urlResponse['body']['format']); @@ -835,7 +836,7 @@ trait DatabasesBase $this->assertEquals(200, $integerResponse['headers']['status-code']); $this->assertEquals($integer['body']['key'], $integerResponse['body']['key']); $this->assertEquals($integer['body']['type'], $integerResponse['body']['type']); - $this->assertEquals('available', $integerResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $integerResponse['body']['status']); $this->assertEquals($integer['body']['required'], $integerResponse['body']['required']); $this->assertEquals($integer['body']['array'], $integerResponse['body']['array']); $this->assertEquals($integer['body']['min'], $integerResponse['body']['min']); @@ -845,7 +846,7 @@ trait DatabasesBase $this->assertEquals(200, $floatResponse['headers']['status-code']); $this->assertEquals($float['body']['key'], $floatResponse['body']['key']); $this->assertEquals($float['body']['type'], $floatResponse['body']['type']); - $this->assertEquals('available', $floatResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $floatResponse['body']['status']); $this->assertEquals($float['body']['required'], $floatResponse['body']['required']); $this->assertEquals($float['body']['array'], $floatResponse['body']['array']); $this->assertEquals($float['body']['min'], $floatResponse['body']['min']); @@ -855,7 +856,7 @@ trait DatabasesBase $this->assertEquals(200, $booleanResponse['headers']['status-code']); $this->assertEquals($boolean['body']['key'], $booleanResponse['body']['key']); $this->assertEquals($boolean['body']['type'], $booleanResponse['body']['type']); - $this->assertEquals('available', $booleanResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $booleanResponse['body']['status']); $this->assertEquals($boolean['body']['required'], $booleanResponse['body']['required']); $this->assertEquals($boolean['body']['array'], $booleanResponse['body']['array']); $this->assertEquals($boolean['body']['default'], $booleanResponse['body']['default']); @@ -863,7 +864,7 @@ trait DatabasesBase $this->assertEquals(200, $datetimeResponse['headers']['status-code']); $this->assertEquals($datetime['body']['key'], $datetimeResponse['body']['key']); $this->assertEquals($datetime['body']['type'], $datetimeResponse['body']['type']); - $this->assertEquals('available', $datetimeResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $datetimeResponse['body']['status']); $this->assertEquals($datetime['body']['required'], $datetimeResponse['body']['required']); $this->assertEquals($datetime['body']['array'], $datetimeResponse['body']['array']); $this->assertEquals($datetime['body']['default'], $datetimeResponse['body']['default']); @@ -871,7 +872,7 @@ trait DatabasesBase $this->assertEquals(200, $relationshipResponse['headers']['status-code']); $this->assertEquals($relationship['body']['key'], $relationshipResponse['body']['key']); $this->assertEquals($relationship['body']['type'], $relationshipResponse['body']['type']); - $this->assertEquals('available', $relationshipResponse['body']['status']); + $this->assertEquals(Status::AVAILABLE, $relationshipResponse['body']['status']); $this->assertEquals($relationship['body']['required'], $relationshipResponse['body']['required']); $this->assertEquals($relationship['body']['array'], $relationshipResponse['body']['array']); $this->assertEquals($relationship['body']['relatedCollection'], $relationshipResponse['body']['relatedCollection']); @@ -1343,7 +1344,7 @@ trait DatabasesBase $this->assertEquals($releaseWithDate1['body']['key'], $movies['body']['indexes'][2]['key']); $this->assertEquals($releaseWithDate2['body']['key'], $movies['body']['indexes'][3]['key']); foreach ($movies['body']['indexes'] as $index) { - $this->assertEquals('available', $index['status']); + $this->assertEquals(Status::AVAILABLE, $index['status']); } return $data; @@ -3785,7 +3786,7 @@ trait DatabasesBase $this->assertEquals(202, $relation['headers']['status-code']); $this->assertEquals('library', $relation['body']['key']); $this->assertEquals('relationship', $relation['body']['type']); - $this->assertEquals('processing', $relation['body']['status']); + $this->assertEquals(Status::CREATING, $relation['body']['status']); $attributes = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes', array_merge([ 'content-type' => 'application/json', @@ -3809,7 +3810,7 @@ trait DatabasesBase ])); $this->assertEquals(200, $attribute['headers']['status-code']); - $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals(Status::AVAILABLE, $attribute['body']['status']); $this->assertEquals('library', $attribute['body']['key']); $this->assertEquals('relationship', $attribute['body']['type']); $this->assertEquals(false, $attribute['body']['required']); @@ -3993,7 +3994,7 @@ trait DatabasesBase ])); $this->assertEquals(200, $attribute['headers']['status-code']); - $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals(Status::AVAILABLE, $attribute['body']['status']); $this->assertEquals('libraries', $attribute['body']['key']); $this->assertEquals('relationship', $attribute['body']['type']); $this->assertEquals(false, $attribute['body']['required']); @@ -4078,7 +4079,7 @@ trait DatabasesBase ])); $this->assertEquals(200, $attribute['headers']['status-code']); - $this->assertEquals('available', $attribute['body']['status']); + $this->assertEquals(Status::AVAILABLE, $attribute['body']['status']); $this->assertEquals('libraries', $attribute['body']['key']); $this->assertEquals('relationship', $attribute['body']['type']); $this->assertEquals(false, $attribute['body']['required']); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 085d3ca01b..2673482352 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Databases; +use Appwrite\Database\Status; use Appwrite\Extend\Exception as AppwriteException; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; @@ -1432,7 +1433,7 @@ class DatabasesCustomServerTest extends Scope $this->assertCount(0, $collection['body']['indexes']); foreach ($collection['body']['attributes'] as $attribute) { - $this->assertEquals('available', $attribute['status'], 'attribute: ' . $attribute['key']); + $this->assertEquals(Status::AVAILABLE, $attribute['status'], 'attribute: ' . $attribute['key']); } // Test indexLimit = 64 diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 6ab2874f8e..6b08271472 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Services\Realtime; +use Appwrite\Database\Status; use CURLFile; use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; @@ -209,7 +210,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals('processing', $response['data']['payload']['status']); + $this->assertEquals(Status::CREATING, $response['data']['payload']['status']); $response = json_decode($client->receive(), true); @@ -229,7 +230,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}", $response['data']['events']); $this->assertContains("databases.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals('available', $response['data']['payload']['status']); + $this->assertEquals(Status::AVAILABLE, $response['data']['payload']['status']); $client->close(); @@ -294,7 +295,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals('processing', $response['data']['payload']['status']); + $this->assertEquals(Status::CREATING, $response['data']['payload']['status']); $response = json_decode($client->receive(), true); @@ -312,7 +313,7 @@ class RealtimeConsoleClientTest extends Scope $this->assertContains("databases.{$databaseId}.collections.*.indexes.*", $response['data']['events']); $this->assertContains("databases.{$databaseId}.collections.*", $response['data']['events']); $this->assertNotEmpty($response['data']['payload']); - $this->assertEquals('available', $response['data']['payload']['status']); + $this->assertEquals(Status::AVAILABLE, $response['data']['payload']['status']); $client->close();