jdavidbakr / MultiServerEvent

Laravel plugin to allow scheduled events across multiple servers with the same scheduler to not overlap.
MIT License
37 stars 17 forks source link

Select after insert causes problems when using read replica DBs #7

Closed paras-malhotra closed 7 years ago

paras-malhotra commented 7 years ago

In the skipMultiServer() method of the Event class, the current code fires a select query right after an insert. Due to Laravel's support for read and write PDOs on the same connection object, this can create inconsistencies like so:

prod.ERROR: exception 'ErrorException' with message 'Undefined offset: 0' in jdavidbakr\MultiServerEvent\Scheduling\Event:108

My recommendation to avoid this issue is as follows:

public function skipMultiserver() {
    $this->key = md5($this->expression . $this->command);
    // Delete any old completed runs that are more than 10 seconds ago
    DB::table($this->lock_table)
        ->where('mutex', $this->key)
        ->where('complete', '<', Carbon::now()->subSeconds(10))
        ->delete();

    $gotLock = true;
    // Attempt to acquire the lock
    try {
        DB::table($this->lock_table)
                ->insert([
                'mutex' => $this->key,
                'lock' => $this->server_id,
                'start' => Carbon::now()
        ]);
    } catch (\PDOException $e) {
        $gotLock = false;
    }

    return $gotLock === false;
}

This not only saves an extra query but also solves the issue at hand

jdavidbakr commented 7 years ago

Fixed in https://github.com/jdavidbakr/MultiServerEvent/commit/e5b471abfd88359834b6770445723dbd93a47c40