All Projects → reshadman → Laravel Optimistic Locking

reshadman / Laravel Optimistic Locking

Licence: mit
Adds optimistic locking feature to eloquent models.

Projects that are alternatives of or similar to Laravel Optimistic Locking

Gorose
GoRose(go orm), a mini database ORM for golang, which inspired by the famous php framwork laravle's eloquent. It will be friendly for php developer and python or ruby developer. Currently provides six major database drivers: mysql,sqlite3,postgres,oracle,mssql, Clickhouse.
Stars: ✭ 947 (+1233.8%)
Mutual labels:  orm, eloquent, database, laravel
Lada Cache
A Redis based, fully automated and scalable database cache layer for Laravel
Stars: ✭ 424 (+497.18%)
Mutual labels:  eloquent, database, laravel
Elasticsearch
The missing elasticsearch ORM for Laravel, Lumen and Native php applications
Stars: ✭ 375 (+428.17%)
Mutual labels:  orm, eloquent, laravel
Analogue
Analogue ORM : Data Mapper ORM for Laravel/PHP
Stars: ✭ 618 (+770.42%)
Mutual labels:  orm, database, laravel
Laravel Tags
Add tags and taggable behaviour to your Laravel app
Stars: ✭ 1,026 (+1345.07%)
Mutual labels:  eloquent, database, laravel
Laravel Database Encryption
A package for automatically encrypting and decrypting Eloquent attributes in Laravel 5.5+, based on configuration settings.
Stars: ✭ 238 (+235.21%)
Mutual labels:  eloquent, database, laravel
Laravel Eloquent Query Cache
Adding cache on your Laravel Eloquent queries' results is now a breeze.
Stars: ✭ 529 (+645.07%)
Mutual labels:  eloquent, database, laravel
Wp Eloquent
Eloquent ORM for WordPress
Stars: ✭ 478 (+573.24%)
Mutual labels:  orm, eloquent, database
Laravel Mongodb
A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)
Stars: ✭ 5,860 (+8153.52%)
Mutual labels:  orm, eloquent, laravel
Laravel
Laravel Model Generator
Stars: ✭ 715 (+907.04%)
Mutual labels:  eloquent, database, laravel
Goloquent
This repo no longer under maintenance, please go to https://github.com/si3nloong/sqlike
Stars: ✭ 16 (-77.46%)
Mutual labels:  orm, eloquent, database
Laravel Migrate Fresh
An artisan command to build up a database from scratch
Stars: ✭ 179 (+152.11%)
Mutual labels:  eloquent, database, laravel
Laravel Settings
Store key value pair in database as settings
Stars: ✭ 107 (+50.7%)
Mutual labels:  eloquent, database, laravel
Sarala
Javascript library to communicate with RESTful API built following JSON API specification. inspired by Laravel’s Eloquent
Stars: ✭ 101 (+42.25%)
Mutual labels:  orm, eloquent, laravel
Laravel Translatable
A Laravel package for multilingual models
Stars: ✭ 624 (+778.87%)
Mutual labels:  eloquent, database, laravel
Eloquent Filter
This simple package helps you filter Eloquent data using query filters.
Stars: ✭ 24 (-66.2%)
Mutual labels:  orm, eloquent, laravel
Eloquent Driver
A package that allows you to store Statamic entries in a database.
Stars: ✭ 28 (-60.56%)
Mutual labels:  eloquent, database, laravel
Laravel Translatable
It's a Laravel database translations manager
Stars: ✭ 47 (-33.8%)
Mutual labels:  database, laravel
Hunt Entity
An object-relational mapping (ORM) framework for D language (Similar to JPA / Doctrine), support PostgreSQL and MySQL.
Stars: ✭ 51 (-28.17%)
Mutual labels:  orm, database
Gormt
database to golang struct
Stars: ✭ 1,063 (+1397.18%)
Mutual labels:  orm, database

Laravel Optimistic Locking

Build Status

Adds optimistic locking feature to Eloquent models.

Installation

composer require reshadman/laravel-optimistic-locking

This package supports Laravel 5.5., 5.6., 5.7., 5.8., and 6.* .

Usage

Basic usage

use the \Reshadman\OptimisticLocking\OptimisticLocking trait in your model:

<?php

class BlogPost extends Model {
    use OptimisticLocking;
}

and add the integer lock_version field to the table of the model:

<?php

$schema->integer('lock_version')->unsigned()->nullable();

Then you are ready to go, if the same resource is edited by two different processes CONCURRENTLY then the following exception will be raised:

<?php
\Reshadman\OptimisticLocking\StaleModelLockingException::class;

You should catch the above exception and act properly based on your business logic.

Maintaining lock_version during business transactions

You can keep track of a lock version during a business transaction by informing your API or HTML client about the current version:

<input type="hidden" name="lock_version" value="{{$blogPost->lock_version}}" 

and in controller:

<?php

// Explicitly setting the lock version
class PostController {
    public function update($id)
    {
        $post = Post::findOrFail($id);
        $post->lock_version = request('lock_version');
        $post->save();
        // You can also define more implicit reusable methods in your model like Model::saveWithVersion(...$args); 
        // or just override the default Model::save(...$args); method which accepts $options
        // Then automatically read the lock version from Request and set into the model.
    }
}

So if two authors are editing the same content concurrently, you can keep track of your Read State, and ask the second author to rewrite his changes.

Disabling and enabling optimistic locking

You can disable and enable optimistic locking for a specific instance:

<?php
$blogPost->disableLocking();
$blogPost->enableLocking();

By default optimistic locking is enabled when you use OptimisticLocking trait in your model, to alter the default behaviour you can set the lock strictly to false:

<?php
class BlogPost extends \Illuminate\Database\Eloquent\Model 
{
    use \Reshadman\OptimisticLocking\OptimisticLocking;
    
    protected $lock = false;
}

and then you may enable it: $blogPost->enableLocking();

Use a different column for tracking version

By default the lock_version column is used for tracking version, you can alter that by overriding the following method of the trait:

<?php
class BlogPost extends \Illuminate\Database\Eloquent\Model
{
    use \Reshadman\OptimisticLocking\OptimisticLocking;
    
    /**
     * Name of the lock version column.
     *
     * @return string
     */
    protected static function lockVersionColumn()
    {
        return 'track_version';
    }
}

What is optimistic locking?

For detailed explanation read the concurrency section of Patterns of Enterprise Application Architecture by Martin Fowler.

There are two way to approach generic concurrency race conditions:

  1. Do not allow other processes (or users) to read and update the same resource (Pessimistic Locking)
  2. Allow other processes to read the same resource concurrently, but do not allow further update, if one of the processes updated the resource before the others (Optimistic locking).

Laravel allows Pessimistic locking as described in the documentation, this package allows you to have Optimistic locking in a rails like way.

What happens during an optimistic lock?

Every time you perform an upsert action to your resource(model), the lock_version counter field in the table is incremented by 1, If you read a resource and another process updates the resource after you read it, the true version counter is incremented by one, If the current process attempts to update the model, simply a StaleModelLockingException will be thrown, and you should handle the race condition (merge, retry, ignore) based on your business logic. That is simply via adding the following criteria to the update query of a optimistically lockable model:

<?php
$query->where('id', $this->id)
    ->where('lock_version', $this->lock_version)
    ->update($changes);

If the resource has been updated before your update attempt, then the above will simply update no records and it means that the model has been updated before current attempt or it has been deleted.

Why don't we use updated_at for tracking changes?

Because they may remain the same during two concurrent updates.

Running tests

Clone the repo, perform a composer install and run:

vendor/bin/phpunit

License

The MIT License (MIT). Please see License File for more information. ense (MIT). Please see License File for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].