Atomic Operations

Modify database values safely without race conditions. Use increment, decrement, multiply, and divide to let the database handle the math.

Why use Atomic Operations?

The Risk

Fetching a value, modifying it in PHP, and saving it back creates a race condition. If two requests happen at once, updates can be lost.

$views = $post->views;
$post->update(['views' => $views + 1]); // ❌ Unsafe
The Fix

Atomic operations push the logic to the database. The database locks the row and calculates the new value reliably.

['views' => ['increment' => 1]] // ✅ Safe

Numeric Operations

These operations work on Int and Float fields.

Controllers/PostController.php
<?php

use Lib\Prisma\Classes\Prisma;

// 1. Increment: Add to a counter (e.g., Post Views)
$post = Prisma::getInstance()->post->update([
    'where' => ['id' => 101],
    'data'  => [
        'views' => ['increment' => 1],
        'likes' => ['increment' => 5]
    ]
]);

// 2. Decrement: Remove from inventory
$product = Prisma::getInstance()->product->update([
    'where' => ['sku' => 'TSHIRT-BLK-L'],
    'data'  => [
        'stock' => ['decrement' => 1]
    ]
]);
Controllers/ProductController.php
<?php

// 3. Multiply: Apply a tax rate or scaling factor
$invoice = Prisma::getInstance()->invoice->update([
    'where' => ['id' => 550],
    'data'  => [
        'totalAmount' => ['multiply' => 1.15] // +15% Tax
    ]
]);

// 4. Divide: Split values or convert units
$stats = Prisma::getInstance()->stats->update([
    'where' => ['day' => 'today'],
    'data'  => [
        'averageTime' => ['divide' => 60] // Seconds to Minutes
    ]
]);

The "Set" Operation

The set operation is used to forcefully overwrite a value. While standard updates (e.g., 'status' => 'active') act as a "set", the explicit syntax is useful when updating lists or ensuring specific type handling in complex schemas.

src/Lib/Services/UserService.php
<?php

// 5. Set: Force a specific value (Atomic replacement)
$user = Prisma::getInstance()->user->update([
    'where' => ['id' => $userId],
    'data'  => [
        'score' => ['set' => 0],            // Reset score to 0
        'tags'  => ['set' => ['banned']]  // Replace all tags
    ]
]);

Pro Tip

Use set when you need to completely replace a list or scalar and don't care about the previous value. Use increment when the change is relative to the current state.

Operation Reference

Operation Input Type Use Case Example Syntax
increment Int, Float Counting views, likes, steps. ['increment' => 1]
decrement Int, Float Reducing inventory, spending credits. ['decrement' => 50]
multiply Int, Float Compound interest, tax application. ['multiply' => 1.05]
divide Int, Float Unit conversion, splitting costs. ['divide' => 2]
set Any Hard resets, overwriting relations. ['set' => 0]

Best Practices

Concurrency

  • Always use decrement for stock/inventory.
  • Never calculate new values in PHP variables for shared data.

Data Types

  • Ensure your DB column allows negative values if decrement can go below zero.
  • Use Float columns for divide operations to avoid rounding errors.