LuaScripts.php 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. namespace Illuminate\Queue;
  3. class LuaScripts
  4. {
  5. /**
  6. * Get the Lua script for computing the size of queue.
  7. *
  8. * KEYS[1] - The name of the primary queue
  9. * KEYS[2] - The name of the "delayed" queue
  10. * KEYS[3] - The name of the "reserved" queue
  11. *
  12. * @return string
  13. */
  14. public static function size()
  15. {
  16. return <<<'LUA'
  17. return redis.call('llen', KEYS[1]) + redis.call('zcard', KEYS[2]) + redis.call('zcard', KEYS[3])
  18. LUA;
  19. }
  20. /**
  21. * Get the Lua script for popping the next job off of the queue.
  22. *
  23. * KEYS[1] - The queue to pop jobs from, for example: queues:foo
  24. * KEYS[2] - The queue to place reserved jobs on, for example: queues:foo:reserved
  25. * ARGV[1] - The time at which the reserved job will expire
  26. *
  27. * @return string
  28. */
  29. public static function pop()
  30. {
  31. return <<<'LUA'
  32. -- Pop the first job off of the queue...
  33. local job = redis.call('lpop', KEYS[1])
  34. local reserved = false
  35. if(job ~= false) then
  36. -- Increment the attempt count and place job on the reserved queue...
  37. reserved = cjson.decode(job)
  38. reserved['attempts'] = reserved['attempts'] + 1
  39. reserved = cjson.encode(reserved)
  40. redis.call('zadd', KEYS[2], ARGV[1], reserved)
  41. end
  42. return {job, reserved}
  43. LUA;
  44. }
  45. /**
  46. * Get the Lua script for releasing reserved jobs.
  47. *
  48. * KEYS[1] - The "delayed" queue we release jobs onto, for example: queues:foo:delayed
  49. * KEYS[2] - The queue the jobs are currently on, for example: queues:foo:reserved
  50. * ARGV[1] - The raw payload of the job to add to the "delayed" queue
  51. * ARGV[2] - The UNIX timestamp at which the job should become available
  52. *
  53. * @return string
  54. */
  55. public static function release()
  56. {
  57. return <<<'LUA'
  58. -- Remove the job from the current queue...
  59. redis.call('zrem', KEYS[2], ARGV[1])
  60. -- Add the job onto the "delayed" queue...
  61. redis.call('zadd', KEYS[1], ARGV[2], ARGV[1])
  62. return true
  63. LUA;
  64. }
  65. /**
  66. * Get the Lua script to migrate expired jobs back onto the queue.
  67. *
  68. * KEYS[1] - The queue we are removing jobs from, for example: queues:foo:reserved
  69. * KEYS[2] - The queue we are moving jobs to, for example: queues:foo
  70. * ARGV[1] - The current UNIX timestamp
  71. *
  72. * @return string
  73. */
  74. public static function migrateExpiredJobs()
  75. {
  76. return <<<'LUA'
  77. -- Get all of the jobs with an expired "score"...
  78. local val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1])
  79. -- If we have values in the array, we will remove them from the first queue
  80. -- and add them onto the destination queue in chunks of 100, which moves
  81. -- all of the appropriate jobs onto the destination queue very safely.
  82. if(next(val) ~= nil) then
  83. redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)
  84. for i = 1, #val, 100 do
  85. redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))
  86. end
  87. end
  88. return val
  89. LUA;
  90. }
  91. }