SHARE
TWEET

Untitled

a guest May 19th, 2019 74 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2.  
  3. namespace GoodbyeDeadlocks
  4.  
  5. use Predis\Client;
  6. use LogicException;
  7.  
  8. class Lock
  9. {
  10.     /**
  11.      * time to keep lock
  12.      * when your script was dead the look will be keeping for that time
  13.      * this is needed when a process is died and will never unlock the wallet
  14.      * metric using minutes, by default = 10 minutes
  15.      * @var integer
  16.      */
  17.     public $ttl = 600;
  18.    
  19.     /**
  20.      * when a lock can't be reached right now script should pause
  21.      * that is needed so you will never hot your redis instance
  22.      * @var integer
  23.      */
  24.     public $delay = 100;
  25.  
  26.     /**
  27.      * we don't want to remove other session locks due invalid logic
  28.      * so this var will keep current locks list
  29.      * @var array
  30.      */
  31.     public $locked = [];
  32.  
  33.     public function __construct(Client $redis)
  34.     {
  35.         $this->redis = $redis;
  36.         register_shutdown_function([$this, 'unlockEverything']);
  37.     }
  38.  
  39.     public function acquire(int $wallet)
  40.     {
  41.         if (func_num_args() > 1) {
  42.             $wallets = func_get_args();
  43.             sort($wallets);
  44.             foreach ($wallets as $wallet) {
  45.                 $this->acquire($wallet);
  46.             }
  47.             return;
  48.         }
  49.  
  50.         if (in_array($wallet, $this->locked)) {
  51.             // simple return true if taken lock is okay
  52.             return true;
  53.             // or throw on exception if you want to discover how it was achieved
  54.             // throw new LogicException("Wallet $wallet was not locked in this session!");
  55.         }
  56.  
  57.         while (!$this->redis->set("wallet-$wallet", 1, 'EX', $this->ttl, 'NX')) {
  58.             usleep($this->delay * 1000);
  59.         }
  60.  
  61.         $this->locked[] = $wallet;
  62.     }
  63.  
  64.     public function remove($wallet)
  65.     {
  66.         if (!in_array($wallet, $this->locked)) {
  67.             throw new LogicException("Wallet $wallet was not locked in this session!");
  68.         }
  69.  
  70.         if (func_num_args() > 1) {
  71.             $wallets = func_get_args();
  72.             sort($wallets);
  73.             foreach ($wallets as $wallet) {
  74.                 $this->remove($wallet);
  75.             }
  76.             return;
  77.         }
  78.  
  79.         $this->redis->del("wallet-$wallet");
  80.     }
  81.  
  82.     public function unlockEverything()
  83.     {
  84.         foreach ($this->locked as $key) {
  85.             $this->remove($key);
  86.         }
  87.     }
  88. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top