AthenaeumAthenaeum
Packages
  • next
  • current
  • v9.x
  • v8.x
  • v7.x
  • v6.x
  • v5.x
  • v4.x
  • v3.x
  • v2.x
  • v1.x
Changelog
GitHub
Packages
  • next
  • current
  • v9.x
  • v8.x
  • v7.x
  • v6.x
  • v5.x
  • v4.x
  • v3.x
  • v2.x
  • v1.x
Changelog
GitHub
  • Version 7.x

    • Release Notes
    • Upgrade Guide
    • New to this...
    • Contribution Guide
    • Security Policy
    • Code of Conduct
    • Origin
  • ACL

    • Introduction
    • How to install
    • Setup
    • Permissions
    • Roles
    • Users
    • Cached Permissions
  • Antivirus

    • Introduction
    • How to install
    • Setup
    • How to use
    • Scanners

      • Introduction
      • ClamAV
      • Null
      • Custom
    • Events
    • PSR
  • Audit

    • Audit
    • How to install
    • Setup
    • Recording
    • Events
  • Auth

    • Introduction
    • How to install
    • Fortify

      • Prerequisites
      • Actions

        • Rehash Password
  • Circuits

    • Circuits
    • How to install
    • Setup
    • Usage
    • Events
  • Collections

    • Collections
    • How to install
    • Summation

      • Summation Collection
      • Items Processor
  • Config

    • Configuration Loader
    • How to install
    • Setup
    • Load Configuration Files
    • Custom File Parsers
  • Console

    • Command and Schedule Registration
    • How to install
    • Setup
    • Commands
    • Schedules
  • Container

    • IoC Service Container
    • How to install
    • Container
    • List Resolver
  • Core

    • Athenaeum Core Application
    • How to install
    • Setup
    • Usage

      • Configuration
      • Service Providers
      • Service Container
      • Events
      • Caching
      • Logging
      • Console
      • Task Scheduling
      • Exception Handling
      • Extending Core Application
      • Testing
  • Database

    • Introduction
    • How to install
    • Models

      • Instantiatable
      • Sluggable
    • Query

      • Criteria (Query Filter)
  • Dto

    • Data Transfer Object (DTO)
    • How to install
    • Create Interface
    • Implement DTO
    • How to use
    • Populate
    • Export
    • Json
    • Serialization
    • Nested DTOs
    • Array DTO
  • ETags

    • Introduction
    • How to install
    • Setup
    • ETags usage

      • How to use
      • Generators

        • Default Generator
        • Custom Generator
      • Eloquent Models
    • Http Request Preconditions

      • Introduction
      • Resource Context
      • Preconditions
      • Actions
      • RFC 9110

        • If-Match
        • If-Unmodified-Since
        • If-None-Match
        • If-Modified-Since
        • If-Range
      • Extensions

        • Introduction
        • Range
      • Range Validator
      • Download Stream
    • Macros
  • Events

    • Register Listeners and Subscribers
    • How to install
    • Setup
    • Listeners
    • Subscribers
  • Filters

    • Search Filter Utilities
    • Prerequisites
    • How to install
    • Setup
    • Processor
    • Filters Builder
    • Predefined Resources

      • Search Processor
      • Sorting Processor
      • Constraints Processor
      • Matching Processor
    • Tip: Create a base builder
  • Flysystem

    • Introduction
    • Database Adapter

      • Introduction
      • How to install
      • Setup
      • Data Deduplication
      • MIME-Type Detection
  • Http

    • Api

      • Http API
      • How to install
      • Setup
      • Resources

        • Introduction
        • Timestamps
        • Self-Link
        • Relations
        • Caching
        • Registrar
      • Requests

        • Introduction
        • List Resources
        • List Deleted
        • Show Resource
        • Create Resource
        • Update Resource
        • Delete Resource
        • List Related
        • Process Multiple Resources
        • Helpers
      • Middleware

        • Introduction
        • Request Must Be Json
        • Capture Fields To Select
        • Remove Response Payload
    • Clients

      • Http Clients
      • How to install
      • Setup
      • Basic Usage
      • Available Methods

        • Fluent Api
        • Protocol Version
        • Base Uri
        • Http Method and Uri
        • Headers
        • Accept & Content-Type
        • Authentication
        • Http Query
        • Payload Format
        • Payload
        • Attachments
        • Cookies
        • Response Expectations
        • Middleware
        • Conditions
        • Criteria
        • Redirects
        • Timeout
        • Debugging
        • Logging
        • Driver Options
        • Driver
      • Http Query Builder

        • Introduction
        • Select
        • Where
        • Dates
        • Include
        • Pagination
        • Sorting
        • Raw Expressions
        • Custom Grammar
    • Cookies

      • Http Cookies
      • How to install
      • Usage
    • Messages

      • Http Messages
      • How to install
      • Serializers
  • Maintenance

    • Modes

      • Maintenance Modes
      • How to install
      • Setup
      • Basic Usage
      • Available Drivers
  • Mime Types

    • MIME-Types
    • How to install
    • Setup
    • Usage
    • Drivers

      • Available Drivers
      • File Info
  • Properties

    • Properties Overload
    • How to install
    • Usage
    • Naming Convention
    • Properties Visibility
  • Redmine

    • Redmine Api Client
    • How to install
    • Setup
    • General Usage

      • Supported Operations
      • Fetch list of resources
      • Find
      • Fetch
      • Create new record
      • Update existing record
      • Delete existing record
      • Relations
    • Available Resources

      • Predefined Resources
      • Attachments
      • Enumerations
      • Issue Relations
      • Users
      • User Groups
      • Roles
      • Project Memberships
      • Versions (Milestones)
      • Issue Categories
      • Trackers
  • Service

    • Service Registrar
    • How to install
    • How to use
  • Streams

    • Streams
    • How to install
    • Setup
    • How to use

      • Introduction
      • Open and Close
      • Raw Resource
      • Seeking
      • Reading
      • Writing
      • Size
      • Truncate
      • Sync
      • Flush
      • Hash
      • MIME-Type
      • Filename
      • Output
      • Locking
      • Transactions
      • Meta
      • Misc
  • Support

    • Introduction
    • How to install
    • Laravel Aware-of Helpers

      • How to use
      • Enforce Via Interface
      • Custom Default
      • Pros and Cons
      • Available Helpers
    • Aware-of Properties

      • Generator
      • Available Aware-of Helpers
    • Live Templates
  • Testing

    • Introduction
    • How to install
    • Test Cases
    • Testing Aware-of Helpers
  • Translation

    • Introduction
    • How to install
    • Exporters

      • Introduction
      • Setup
      • How to use
      • Drivers

        • Introduction
        • Array
        • Lang.js (Array)
        • Lang.js (JSON)
        • Cache
  • Utils

    • Introduction
    • How to install
    • Array
    • Duration
    • Json
    • Math
    • Memory
    • Method Helper
    • Invoker
    • Populatable
    • String
    • Version
  • Validation

    • Introduction
    • How to install
    • Setup
    • Rules

      • Alpha-Dash-Dot
      • Date Format
      • Semantic Version
You are viewing documentation for an outdated version. It is no longer supported!

Locking

The FileStream component offers a simple locking mechanism, which uses PHP's flock() to acquire and release a lock. In this section, a few examples are shown on how to acquire a lock and perform operations on a file.

  • Exclusive Lock
  • Shared Lock
  • Customise Behaviour
    • Outside Laravel
  • Custom Lock Drivers

Exclusive Lock

To acquire an exclusive lock (LOCK_EX) and perform some kind of write operation on the stream, use the exclusiveLock() method.

The method accepts the following arguments:

  • callable $operation: Callback to be invoked after lock was acquired. The stream instance is given as argument to callback.
  • float $timeout: (optional) Timeout of acquiring lock in seconds. Defaults to 0.5 seconds.
  • string|null $profile: (optional) Name of locking profile to use (See Customise Behaviour).
  • array $options: (optional) Lock driver specific options (See Customise Behaviour).

Once the callback has been performed, the lock is automatically released.

// Assuming file is empty...
$stream = FileStream::open('persons.txt', 'r+b');

$result = $stream->exclusiveLock(function($stream) {
    // ...Do something with stream...
    $stream->put("\nJohn");
    
    return (string) $stream;
});

echo $result; // John

Shared Lock

If you wish to acquire a shared lock (LOCK_SH), use the sharedLock() method.

Method accepts the same type of arguments as exclusiveLock().

// Assuming file has "Jim" as content
$stream = FileStream::open('persons.txt', 'r+b');

$result = $stream->sharedLock(function($stream) {    
    return (string) $stream;
});

echo $result; // Jim

Customise Behaviour

If you are using the streams component inside a Laravel application, then you can customise the locking behaviour via the config/streams.php configuration. Here, you may change existing lock profiles or add new ones.

return [

    // ...previous not shown...

    /*
     |--------------------------------------------------------------------------
     | Lock profiles
     |--------------------------------------------------------------------------
    */

    'locks' => [

        // ...default profile not shown here...
        
        'my-lock-profile' => [
            'driver' => \Aedart\Streams\Locks\Drivers\FLockDriver::class,
            'options' => [
                'sleep' => 5_000,
                'fail_on_timeout' => true
            ]
        ]
    ],
    
    // ... remaining not shown...
];

Then, when you wish for your stream to acquire a lock using a specific lock profile, specify the profile for the $profile argument.

$result = $stream->exclusiveLock(function($stream) {
    // ...not shown...
}, 0.01, 'my-lock-profile');

You can also choose to overwrite a given profile's options, when acquiring the lock, via the $options argument.

// Custom options for a single operation...
$options = [
    'sleep' => 2_000
];

$result = $stream->exclusiveLock(function($stream) {
    // ...not shown...
}, 0.01, 'my-lock-profile', $options);

Outside Laravel

If you wish to customise the locking behaviour whilst using this package outside a regular Laravel application, then you have a few ways to do so:

  • You can specify custom $options, which can configure the "default" profile.
  • Set "profiles" manually on the internal LockFactory

Specify custom options

// Custom options for a single operation...
$options = [
    'sleep' => 12_000,
    'fail_on_timeout' => false
];

$result = $stream->exclusiveLock(function($stream) {
    // ...not shown...
}, 0.01, null, $options);

Specify custom "profiles"

A list of custom profiles can always be specified on a stream's internal LockFactory.

use \Aedart\Streams\Locks\Drivers\FLockDriver;

/** @type \Aedart\Streams\Locks\LockFactory $lockFactory */
$lockFactory = $stream
    ->getLockFactory();
    ->usingProfiles([
        'my-profile' => [
            'driver' => FLockDriver::class,
            'options' => [
                'sleep' => 10_000,
                'fail_on_timeout' => true
            ]
        ]
        
        // ...more profiles...
    ])
    ->defaultProfile('my-profile')

Unfortunately, the above shown example is not very practical, if you have to do this for every stream instance. Therefore, to overcome this issue, you are encouraged to extend the FileStream component and overwrite the getDefaultLockFactory() method.

use Aedart\Streams\FileStream;
use Aedart\Streams\Locks\LockFactory;
use Aedart\Contracts\Streams\Locks\Factory;

class MyFileStream extends FileStream
{
    public function getDefaultLockFactory(): Factory|null
    {
        $profiles = [
            'my-profile' => [
                'driver' => FLockDriver::class,
                'options' => [
                    'sleep' => 10_000,
                    'fail_on_timeout' => true
                ]
            ]
            
            // ...more profiles...
        ];
    
        $default = 'my-profile';
    
        return new LockFactory($profiles, $default);
    }
}

Custom Lock Drivers

Should the default provided FLockDriver not be a good solution for you, then you can always add your own custom driver(s). The easiest way of doing so, is by extending the BaseLockDriver abstraction.

use Aedart\Streams\Locks\Drivers\BaseLockDriver;

class MyLockDriver extends BaseLockDriver
{
    public function acquireLock(Stream $stream, int $type, float $timeout): bool
    {
        // ...not shown...
    }
    
    public function releaseLock(Stream $stream): bool
    {
        // ...not shown...
    }
}

Once you have you driver implemented, then you can specify it as a profile's driver:

// Where you specify your profiles...
$profiles = [
    'my-profile' => [
        'driver' => MyLockDriver::class,
        // ... remaining not shown ...
    ]
    
    // ...more profiles...
];
Edit page
Last Updated: 18/03/2024, 10:45
Contributors: Alin Eugen Deac, alin
Prev
Output
Next
Transactions