mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Update DB
This commit is contained in:
+1
-1
@@ -161,7 +161,7 @@ class Upsert extends Action
|
||||
|
||||
try {
|
||||
$modified = $dbForProject->withPreserveDates(function () use ($dbForProject, $database, $collection, $documents, $plan, &$upserted) {
|
||||
return $dbForProject->createOrUpdateDocuments(
|
||||
return $dbForProject->upsertDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$documents,
|
||||
onNext: function (Document $document) use ($plan, &$upserted) {
|
||||
|
||||
+1
-1
@@ -299,7 +299,7 @@ class Upsert extends Action
|
||||
$upserted = [];
|
||||
try {
|
||||
$dbForProject->withPreserveDates(function () use (&$upserted, $dbForProject, $database, $collection, $newDocument) {
|
||||
return $dbForProject->createOrUpdateDocuments(
|
||||
return $dbForProject->upsertDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
[$newDocument],
|
||||
onNext: function (Document $document) use (&$upserted) {
|
||||
|
||||
@@ -12,9 +12,11 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response as UtopiaResponse;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Authorization;
|
||||
use Utopia\Database\Exception\Conflict as ConflictException;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
use Utopia\Database\Exception\NotFound as NotFoundException;
|
||||
use Utopia\Database\Exception\Structure;
|
||||
use Utopia\Database\Exception\Transaction as TransactionException;
|
||||
use Utopia\Database\Query;
|
||||
use Utopia\Database\Validator\UID;
|
||||
@@ -65,6 +67,23 @@ class Update extends Action
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $transactionId
|
||||
* @param bool $commit
|
||||
* @param bool $rollback
|
||||
* @param UtopiaResponse $response
|
||||
* @param Database $dbForProject
|
||||
* @param Delete $queueForDeletes
|
||||
* @return void
|
||||
* @throws ConflictException
|
||||
* @throws Exception
|
||||
* @throws \DateMalformedStringException
|
||||
* @throws \Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws Authorization
|
||||
* @throws Structure
|
||||
* @throws \Utopia\Exception
|
||||
*/
|
||||
public function action(string $transactionId, bool $commit, bool $rollback, UtopiaResponse $response, Database $dbForProject, Delete $queueForDeletes): void
|
||||
{
|
||||
if (!$commit && !$rollback) {
|
||||
@@ -113,149 +132,38 @@ class Update extends Action
|
||||
$action = $operation['action'];
|
||||
$data = $operation['data'];
|
||||
|
||||
// Check if this operation depends on documents created in same transaction
|
||||
$dependent = \in_array($action, ['update', 'increment', 'decrement'])
|
||||
&& isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Don't use timestamp wrapper for dependent operations
|
||||
switch ($action) {
|
||||
case 'update':
|
||||
// Update the state document directly
|
||||
$existing = $state[$collectionId][$documentId];
|
||||
foreach ($data as $key => $value) {
|
||||
$existing->setAttribute($key, $value);
|
||||
}
|
||||
$state[$collectionId][$documentId] = $dbForProject->updateDocument(
|
||||
$collectionId,
|
||||
$documentId,
|
||||
$existing
|
||||
);
|
||||
break;
|
||||
|
||||
case 'increment':
|
||||
$state[$collectionId][$documentId] = $dbForProject->increaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
max: $data['max'] ?? null
|
||||
);
|
||||
break;
|
||||
|
||||
case 'decrement':
|
||||
$state[$collectionId][$documentId] = $dbForProject->decreaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
min: $data['min'] ?? null
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $queueForDeletes, $action, $collectionId, $documentId, $data, &$state) {
|
||||
switch ($action) {
|
||||
case 'create':
|
||||
if ($documentId && !isset($data['$id'])) {
|
||||
$data['$id'] = $documentId;
|
||||
}
|
||||
$state[$collectionId][$documentId] = $dbForProject->createDocument(
|
||||
$collectionId,
|
||||
new Document($data),
|
||||
);
|
||||
break;
|
||||
|
||||
case 'update':
|
||||
$document = $dbForProject->updateDocument(
|
||||
$collectionId,
|
||||
$documentId,
|
||||
new Document($data),
|
||||
);
|
||||
|
||||
if ($document->isEmpty()) {
|
||||
throw new ConflictException('');
|
||||
}
|
||||
|
||||
$state[$collectionId][$documentId] = $document;
|
||||
break;
|
||||
|
||||
case 'upsert':
|
||||
$document = new Document($data);
|
||||
$dbForProject->createOrUpdateDocuments(
|
||||
$collectionId,
|
||||
[$document],
|
||||
onNext: function (Document $document) use (&$state, $collectionId) {
|
||||
$state[$collectionId][$document->getId()] = $document;
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
$dbForProject->deleteDocument($collectionId, $documentId);
|
||||
|
||||
if (isset($state[$collectionId][$documentId])) {
|
||||
unset($state[$collectionId][$documentId]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'increment':
|
||||
$dbForProject->increaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
max: $data['max'] ?? null
|
||||
);
|
||||
break;
|
||||
|
||||
case 'decrement':
|
||||
$dbForProject->decreaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
min: $data['min'] ?? null
|
||||
);
|
||||
break;
|
||||
|
||||
case 'bulkCreate':
|
||||
$dbForProject->createDocuments(
|
||||
$collectionId,
|
||||
$data,
|
||||
onNext: function (Document $document) use (&$state, $collectionId) {
|
||||
$state[$collectionId][$document->getId()] = $document;
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'bulkUpdate':
|
||||
$dbForProject->updateDocuments(
|
||||
$collectionId,
|
||||
new Document($data['data']),
|
||||
Query::parseQueries($data['queries'] ?? [])
|
||||
);
|
||||
break;
|
||||
|
||||
case 'bulkUpsert':
|
||||
$dbForProject->createOrUpdateDocuments(
|
||||
$collectionId,
|
||||
$data,
|
||||
onNext: function (Document $document) use (&$state, $collectionId) {
|
||||
$state[$collectionId][$document->getId()] = $document;
|
||||
}
|
||||
);
|
||||
break;
|
||||
|
||||
case 'bulkDelete':
|
||||
$dbForProject->deleteDocuments(
|
||||
$collectionId,
|
||||
Query::parseQueries($data['queries'] ?? [])
|
||||
);
|
||||
break;
|
||||
}
|
||||
});
|
||||
// Execute the operation based on its type
|
||||
switch ($action) {
|
||||
case 'create':
|
||||
$this->handleCreateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'update':
|
||||
$this->handleUpdateOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'upsert':
|
||||
$this->handleUpsertOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'delete':
|
||||
$this->handleDeleteOperation($dbForProject, $collectionId, $documentId, $createdAt, $state);
|
||||
break;
|
||||
case 'increment':
|
||||
$this->handleIncrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'decrement':
|
||||
$this->handleDecrementOperation($dbForProject, $collectionId, $documentId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'bulkCreate':
|
||||
$this->handleBulkCreateOperation($dbForProject, $collectionId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'bulkUpdate':
|
||||
$this->handleBulkUpdateOperation($dbForProject, $collectionId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'bulkUpsert':
|
||||
$this->handleBulkUpsertOperation($dbForProject, $collectionId, $data, $createdAt, $state);
|
||||
break;
|
||||
case 'bulkDelete':
|
||||
$this->handleBulkDeleteOperation($dbForProject, $collectionId, $data, $createdAt, $state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +177,6 @@ class Update extends Action
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($transaction);
|
||||
|
||||
} catch (NotFoundException $e) {
|
||||
$dbForProject->updateDocument('transactions', $transactionId, new Document([
|
||||
'status' => 'failed',
|
||||
@@ -290,17 +197,351 @@ class Update extends Action
|
||||
}
|
||||
|
||||
if ($rollback) {
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($transaction);
|
||||
|
||||
$transaction = $dbForProject->updateDocument('transactions', $transactionId, new Document([
|
||||
'status' => 'rolledBack',
|
||||
]));
|
||||
|
||||
$queueForDeletes
|
||||
->setType(DELETE_TYPE_DOCUMENT)
|
||||
->setDocument($transaction);
|
||||
}
|
||||
|
||||
$response
|
||||
->setStatusCode(SwooleResponse::STATUS_CODE_OK)
|
||||
->dynamic($transaction, UtopiaResponse::MODEL_TRANSACTION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle create operation
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
private function handleCreateOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
?string $documentId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
if ($documentId && !isset($data['$id'])) {
|
||||
$data['$id'] = $documentId;
|
||||
}
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $data, &$state) {
|
||||
$state[$collectionId][$data['$id']] = $dbForProject->createDocument(
|
||||
$collectionId,
|
||||
new Document($data),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle update operation
|
||||
* @throws ConflictException
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
private function handleUpdateOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
string $documentId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dependent = isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Update the state document directly without timestamp wrapper
|
||||
$state[$collectionId][$documentId] = $dbForProject->updateDocument(
|
||||
$collectionId,
|
||||
$documentId,
|
||||
new Document($data),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data, &$state) {
|
||||
$document = $dbForProject->updateDocument(
|
||||
$collectionId,
|
||||
$documentId,
|
||||
new Document($data),
|
||||
);
|
||||
if ($document->isEmpty()) {
|
||||
throw new ConflictException('');
|
||||
}
|
||||
$state[$collectionId][$documentId] = $document;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle upsert operation
|
||||
* @throws \Utopia\Database\Exception
|
||||
*/
|
||||
private function handleUpsertOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
?string $documentId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dependent = isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Upsert the state document directly without timestamp wrapper
|
||||
$state[$collectionId][$documentId] = $dbForProject->upsertDocument(
|
||||
$collectionId,
|
||||
new Document($data),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data, &$state) {
|
||||
$state[$collectionId][$documentId] = $dbForProject->upsertDocument(
|
||||
$collectionId,
|
||||
new Document($data),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle delete operation
|
||||
*/
|
||||
private function handleDeleteOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
string $documentId,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dependent = isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Delete without timestamp wrapper
|
||||
$dbForProject->deleteDocument($collectionId, $documentId);
|
||||
unset($state[$collectionId][$documentId]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, &$state) {
|
||||
$dbForProject->deleteDocument($collectionId, $documentId);
|
||||
if (isset($state[$collectionId][$documentId])) {
|
||||
unset($state[$collectionId][$documentId]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle increment operation
|
||||
*/
|
||||
private function handleIncrementOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
string $documentId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dependent = isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Increment without timestamp wrapper
|
||||
$state[$collectionId][$documentId] = $dbForProject->increaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
max: $data['max'] ?? null
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data) {
|
||||
$dbForProject->increaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
max: $data['max'] ?? null
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle decrement operation
|
||||
*/
|
||||
private function handleDecrementOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
string $documentId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dependent = isset($state[$collectionId][$documentId]);
|
||||
|
||||
if ($dependent) {
|
||||
// Decrement without timestamp wrapper
|
||||
$state[$collectionId][$documentId] = $dbForProject->decreaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
min: $data['min'] ?? null
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use timestamp wrapper for independent operations
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $documentId, $data) {
|
||||
$dbForProject->decreaseDocumentAttribute(
|
||||
collection: $collectionId,
|
||||
id: $documentId,
|
||||
attribute: $data['attribute'],
|
||||
value: $data['value'] ?? 1,
|
||||
min: $data['min'] ?? null
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk create operation
|
||||
*/
|
||||
private function handleBulkCreateOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$dbForProject->withRequestTimestamp($createdAt, function () use ($dbForProject, $collectionId, $data, &$state) {
|
||||
$dbForProject->createDocuments(
|
||||
$collectionId,
|
||||
$data,
|
||||
onNext: function (Document $document) use (&$state, $collectionId) {
|
||||
$state[$collectionId][$document->getId()] = $document;
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk update operation with manual timestamp checking
|
||||
* @throws \Utopia\Database\Exception
|
||||
* @throws \Utopia\Database\Exception\Query
|
||||
* @throws ConflictException
|
||||
*/
|
||||
private function handleBulkUpdateOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$queries = Query::parseQueries($data['queries'] ?? []);
|
||||
|
||||
$dbForProject->updateDocuments(
|
||||
$collectionId,
|
||||
new Document($data['data']),
|
||||
$queries,
|
||||
onNext: function (Document $updated, Document $old) use (&$state, $collectionId, $createdAt) {
|
||||
// Check if this document was created/modified in this transaction
|
||||
$dependent = isset($state[$collectionId][$updated->getId()]);
|
||||
|
||||
// If not in transaction state, check for timestamp conflicts
|
||||
if (!$dependent) {
|
||||
$oldUpdatedAt = new \DateTime($old->getUpdatedAt());
|
||||
if ($oldUpdatedAt > $createdAt) {
|
||||
throw new ConflictException('Document was updated after the request timestamp');
|
||||
}
|
||||
}
|
||||
|
||||
$state[$collectionId][$updated->getId()] = $updated;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk upsert operation with manual timestamp checking
|
||||
* @throws ConflictException
|
||||
*/
|
||||
private function handleBulkUpsertOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
// Run bulk upsert without timestamp wrapper, checking manually in callback
|
||||
$dbForProject->upsertDocuments(
|
||||
$collectionId,
|
||||
$data,
|
||||
onNext: function (Document $upserted, ?Document $old) use (&$state, $collectionId, $createdAt) {
|
||||
if ($old !== null) {
|
||||
// This is an update - check if document was created/modified in this transaction
|
||||
$dependent = isset($state[$collectionId][$upserted->getId()]);
|
||||
|
||||
// If not in transaction state, check for timestamp conflicts
|
||||
if (!$dependent) {
|
||||
$oldUpdatedAt = new \DateTime($old->getUpdatedAt());
|
||||
if ($oldUpdatedAt > $createdAt) {
|
||||
throw new ConflictException('Document was updated after the request timestamp');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If $old is null, this is a create operation - no timestamp check needed
|
||||
$state[$collectionId][$upserted->getId()] = $upserted;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bulk delete operation with manual timestamp checking
|
||||
* @throws \Utopia\Database\Exception\Query
|
||||
* @throws ConflictException
|
||||
*/
|
||||
private function handleBulkDeleteOperation(
|
||||
Database $dbForProject,
|
||||
string $collectionId,
|
||||
array $data,
|
||||
\DateTime $createdAt,
|
||||
array &$state
|
||||
): void
|
||||
{
|
||||
$queries = Query::parseQueries($data['queries'] ?? []);
|
||||
|
||||
$dbForProject->deleteDocuments(
|
||||
$collectionId,
|
||||
$queries,
|
||||
onNext: function (Document $deleted, Document $old) use (&$state, $collectionId, $createdAt) {
|
||||
$dependent = isset($state[$collectionId][$deleted->getId()]);
|
||||
|
||||
// If not in transaction state, check for timestamp conflicts
|
||||
if (!$dependent) {
|
||||
$oldUpdatedAt = new \DateTime($old->getUpdatedAt());
|
||||
if ($oldUpdatedAt > $createdAt) {
|
||||
throw new ConflictException('Document was updated after the transaction operation');
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from state after successful deletion
|
||||
if (isset($state[$collectionId][$deleted->getId()])) {
|
||||
unset($state[$collectionId][$deleted->getId()]);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -432,7 +432,7 @@ class StatsResources extends Action
|
||||
|
||||
protected function writeDocuments(Database $dbForLogs, Document $project): void
|
||||
{
|
||||
$dbForLogs->createOrUpdateDocuments(
|
||||
$dbForLogs->upsertDocuments(
|
||||
'stats',
|
||||
$this->documents
|
||||
);
|
||||
|
||||
@@ -424,7 +424,7 @@ class StatsUsage extends Action
|
||||
try {
|
||||
$dbForProject = $getProjectDB($projectStats['project']);
|
||||
Console::log('Processing batch with ' . count($projectStats['stats']) . ' stats');
|
||||
$dbForProject->createOrUpdateDocumentsWithIncrease('stats', 'value', $projectStats['stats']);
|
||||
$dbForProject->upsertDocumentsWithIncrease('stats', 'value', $projectStats['stats']);
|
||||
Console::success('Batch successfully written to DB');
|
||||
|
||||
unset($this->projects[$sequence]);
|
||||
@@ -468,7 +468,7 @@ class StatsUsage extends Action
|
||||
|
||||
try {
|
||||
Console::log('Processing batch with ' . count($this->statDocuments) . ' stats');
|
||||
$dbForLogs->createOrUpdateDocumentsWithIncrease(
|
||||
$dbForLogs->upsertDocumentsWithIncrease(
|
||||
'stats',
|
||||
'value',
|
||||
$this->statDocuments
|
||||
|
||||
Reference in New Issue
Block a user