Encapsulate locks mechanics in "ProcessLock" class

This commit is contained in:
Dmitriy Simushev 2014-10-30 12:25:48 +00:00
parent 22699f1ed5
commit b3c9a02660
2 changed files with 99 additions and 12 deletions

View File

@ -0,0 +1,95 @@
<?php
/*
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew;
use Mibew\Settings;
/**
* Watch the process is ran only once.
*/
class ProcessLock
{
/**
* Name of the lock.
*
* @var string
*/
private $name;
/**
* Time to live of the lock.
*
* @var int
*/
private $ttl;
/**
* Class constructor.
*
* @param string $name Name of the lock.
* @param int $ttl Time after the lock will be automatically released.
*/
public function __construct($name, $ttl = 300)
{
$this->name = $name;
$this->ttl = $ttl;
}
/**
* Tries to get the lock.
*
* @return boolean True if the lock has been got and false otherwise.
*/
public function get()
{
// Check if we can get the lock
$lock_timestamp = (int)Settings::get($this->getInternalName(), 0);
$is_lock_free = !$lock_timestamp
// Lock cannot be got for more than ttl.
|| (time() - $lock_timestamp) > $this->ttl;
if (!$is_lock_free) {
return false;
}
// Get the lock
Settings::set($this->getInternalName(), time());
return true;
}
/**
* Releases the lock
*/
public function release()
{
Settings::set($this->getInternalName(), '0');
}
/**
* Builds internal name of the lock.
*
* @return string
*/
protected function getInternalName()
{
return '_' . $this->name . '_lock_time';
}
}

View File

@ -382,18 +382,10 @@ class Thread
return;
}
// We need to run only one instance of cleaning process. Use a lock with
// last run timestamp.
$lock_timestamp = (int)Settings::get('_threads_close_old_lock_time', 0);
$is_lock_free = !$lock_timestamp
// Lock cannot be got for more than 5 minutes. If such situation
// take place we have a deadlock.
|| (time() - $lock_timestamp) > 5 * 60;
if ($is_lock_free) {
// Get the lock
Settings::set('_threads_close_old_lock_time', time());
// We need to run only one instance of cleaning process.
$lock = new ProcessLock('threads_close_old');
if ($lock->get()) {
$query = "SELECT * FROM {thread} "
. "WHERE istate <> :state_closed "
. "AND istate <> :state_left "
@ -454,7 +446,7 @@ class Thread
}
// Release the lock
Settings::set('_threads_close_old_lock_time', '0');
$lock->release();
}
}