PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/laravel/framework/src/Illuminate/Bus/DatabaseBatchRepository.php

https://gitlab.com/jjpa2018/dashboard
PHP | 347 lines | 186 code | 38 blank | 123 comment | 4 complexity | b60566f02f2f0b96df5bd70eb7d098a5 MD5 | raw file
  1. <?php
  2. namespace Illuminate\Bus;
  3. use Carbon\CarbonImmutable;
  4. use Closure;
  5. use DateTimeInterface;
  6. use Illuminate\Database\Connection;
  7. use Illuminate\Database\PostgresConnection;
  8. use Illuminate\Database\Query\Expression;
  9. use Illuminate\Support\Str;
  10. class DatabaseBatchRepository implements PrunableBatchRepository
  11. {
  12. /**
  13. * The batch factory instance.
  14. *
  15. * @var \Illuminate\Bus\BatchFactory
  16. */
  17. protected $factory;
  18. /**
  19. * The database connection instance.
  20. *
  21. * @var \Illuminate\Database\Connection
  22. */
  23. protected $connection;
  24. /**
  25. * The database table to use to store batch information.
  26. *
  27. * @var string
  28. */
  29. protected $table;
  30. /**
  31. * Create a new batch repository instance.
  32. *
  33. * @param \Illuminate\Bus\BatchFactory $factory
  34. * @param \Illuminate\Database\Connection $connection
  35. * @param string $table
  36. */
  37. public function __construct(BatchFactory $factory, Connection $connection, string $table)
  38. {
  39. $this->factory = $factory;
  40. $this->connection = $connection;
  41. $this->table = $table;
  42. }
  43. /**
  44. * Retrieve a list of batches.
  45. *
  46. * @param int $limit
  47. * @param mixed $before
  48. * @return \Illuminate\Bus\Batch[]
  49. */
  50. public function get($limit = 50, $before = null)
  51. {
  52. return $this->connection->table($this->table)
  53. ->orderByDesc('id')
  54. ->take($limit)
  55. ->when($before, function ($q) use ($before) {
  56. return $q->where('id', '<', $before);
  57. })
  58. ->get()
  59. ->map(function ($batch) {
  60. return $this->toBatch($batch);
  61. })
  62. ->all();
  63. }
  64. /**
  65. * Retrieve information about an existing batch.
  66. *
  67. * @param string $batchId
  68. * @return \Illuminate\Bus\Batch|null
  69. */
  70. public function find(string $batchId)
  71. {
  72. $batch = $this->connection->table($this->table)
  73. ->where('id', $batchId)
  74. ->first();
  75. if ($batch) {
  76. return $this->toBatch($batch);
  77. }
  78. }
  79. /**
  80. * Store a new pending batch.
  81. *
  82. * @param \Illuminate\Bus\PendingBatch $batch
  83. * @return \Illuminate\Bus\Batch
  84. */
  85. public function store(PendingBatch $batch)
  86. {
  87. $id = (string) Str::orderedUuid();
  88. $this->connection->table($this->table)->insert([
  89. 'id' => $id,
  90. 'name' => $batch->name,
  91. 'total_jobs' => 0,
  92. 'pending_jobs' => 0,
  93. 'failed_jobs' => 0,
  94. 'failed_job_ids' => '[]',
  95. 'options' => $this->serialize($batch->options),
  96. 'created_at' => time(),
  97. 'cancelled_at' => null,
  98. 'finished_at' => null,
  99. ]);
  100. return $this->find($id);
  101. }
  102. /**
  103. * Increment the total number of jobs within the batch.
  104. *
  105. * @param string $batchId
  106. * @param int $amount
  107. * @return void
  108. */
  109. public function incrementTotalJobs(string $batchId, int $amount)
  110. {
  111. $this->connection->table($this->table)->where('id', $batchId)->update([
  112. 'total_jobs' => new Expression('total_jobs + '.$amount),
  113. 'pending_jobs' => new Expression('pending_jobs + '.$amount),
  114. 'finished_at' => null,
  115. ]);
  116. }
  117. /**
  118. * Decrement the total number of pending jobs for the batch.
  119. *
  120. * @param string $batchId
  121. * @param string $jobId
  122. * @return \Illuminate\Bus\UpdatedBatchJobCounts
  123. */
  124. public function decrementPendingJobs(string $batchId, string $jobId)
  125. {
  126. $values = $this->updateAtomicValues($batchId, function ($batch) use ($jobId) {
  127. return [
  128. 'pending_jobs' => $batch->pending_jobs - 1,
  129. 'failed_jobs' => $batch->failed_jobs,
  130. 'failed_job_ids' => json_encode(array_values(array_diff(json_decode($batch->failed_job_ids, true), [$jobId]))),
  131. ];
  132. });
  133. return new UpdatedBatchJobCounts(
  134. $values['pending_jobs'],
  135. $values['failed_jobs']
  136. );
  137. }
  138. /**
  139. * Increment the total number of failed jobs for the batch.
  140. *
  141. * @param string $batchId
  142. * @param string $jobId
  143. * @return \Illuminate\Bus\UpdatedBatchJobCounts
  144. */
  145. public function incrementFailedJobs(string $batchId, string $jobId)
  146. {
  147. $values = $this->updateAtomicValues($batchId, function ($batch) use ($jobId) {
  148. return [
  149. 'pending_jobs' => $batch->pending_jobs,
  150. 'failed_jobs' => $batch->failed_jobs + 1,
  151. 'failed_job_ids' => json_encode(array_values(array_unique(array_merge(json_decode($batch->failed_job_ids, true), [$jobId])))),
  152. ];
  153. });
  154. return new UpdatedBatchJobCounts(
  155. $values['pending_jobs'],
  156. $values['failed_jobs']
  157. );
  158. }
  159. /**
  160. * Update an atomic value within the batch.
  161. *
  162. * @param string $batchId
  163. * @param \Closure $callback
  164. * @return int|null
  165. */
  166. protected function updateAtomicValues(string $batchId, Closure $callback)
  167. {
  168. return $this->connection->transaction(function () use ($batchId, $callback) {
  169. $batch = $this->connection->table($this->table)->where('id', $batchId)
  170. ->lockForUpdate()
  171. ->first();
  172. return is_null($batch) ? [] : tap($callback($batch), function ($values) use ($batchId) {
  173. $this->connection->table($this->table)->where('id', $batchId)->update($values);
  174. });
  175. });
  176. }
  177. /**
  178. * Mark the batch that has the given ID as finished.
  179. *
  180. * @param string $batchId
  181. * @return void
  182. */
  183. public function markAsFinished(string $batchId)
  184. {
  185. $this->connection->table($this->table)->where('id', $batchId)->update([
  186. 'finished_at' => time(),
  187. ]);
  188. }
  189. /**
  190. * Cancel the batch that has the given ID.
  191. *
  192. * @param string $batchId
  193. * @return void
  194. */
  195. public function cancel(string $batchId)
  196. {
  197. $this->connection->table($this->table)->where('id', $batchId)->update([
  198. 'cancelled_at' => time(),
  199. 'finished_at' => time(),
  200. ]);
  201. }
  202. /**
  203. * Delete the batch that has the given ID.
  204. *
  205. * @param string $batchId
  206. * @return void
  207. */
  208. public function delete(string $batchId)
  209. {
  210. $this->connection->table($this->table)->where('id', $batchId)->delete();
  211. }
  212. /**
  213. * Prune all of the entries older than the given date.
  214. *
  215. * @param \DateTimeInterface $before
  216. * @return int
  217. */
  218. public function prune(DateTimeInterface $before)
  219. {
  220. $query = $this->connection->table($this->table)
  221. ->whereNotNull('finished_at')
  222. ->where('finished_at', '<', $before->getTimestamp());
  223. $totalDeleted = 0;
  224. do {
  225. $deleted = $query->take(1000)->delete();
  226. $totalDeleted += $deleted;
  227. } while ($deleted !== 0);
  228. return $totalDeleted;
  229. }
  230. /**
  231. * Prune all of the unfinished entries older than the given date.
  232. *
  233. * @param \DateTimeInterface $before
  234. * @return int
  235. */
  236. public function pruneUnfinished(DateTimeInterface $before)
  237. {
  238. $query = $this->connection->table($this->table)
  239. ->whereNull('finished_at')
  240. ->where('created_at', '<', $before->getTimestamp());
  241. $totalDeleted = 0;
  242. do {
  243. $deleted = $query->take(1000)->delete();
  244. $totalDeleted += $deleted;
  245. } while ($deleted !== 0);
  246. return $totalDeleted;
  247. }
  248. /**
  249. * Execute the given Closure within a storage specific transaction.
  250. *
  251. * @param \Closure $callback
  252. * @return mixed
  253. */
  254. public function transaction(Closure $callback)
  255. {
  256. return $this->connection->transaction(function () use ($callback) {
  257. return $callback();
  258. });
  259. }
  260. /**
  261. * Serialize the given value.
  262. *
  263. * @param mixed $value
  264. * @return string
  265. */
  266. protected function serialize($value)
  267. {
  268. $serialized = serialize($value);
  269. return $this->connection instanceof PostgresConnection
  270. ? base64_encode($serialized)
  271. : $serialized;
  272. }
  273. /**
  274. * Unserialize the given value.
  275. *
  276. * @param string $serialized
  277. * @return mixed
  278. */
  279. protected function unserialize($serialized)
  280. {
  281. if ($this->connection instanceof PostgresConnection &&
  282. ! Str::contains($serialized, [':', ';'])) {
  283. $serialized = base64_decode($serialized);
  284. }
  285. return unserialize($serialized);
  286. }
  287. /**
  288. * Convert the given raw batch to a Batch object.
  289. *
  290. * @param object $batch
  291. * @return \Illuminate\Bus\Batch
  292. */
  293. protected function toBatch($batch)
  294. {
  295. return $this->factory->make(
  296. $this,
  297. $batch->id,
  298. $batch->name,
  299. (int) $batch->total_jobs,
  300. (int) $batch->pending_jobs,
  301. (int) $batch->failed_jobs,
  302. json_decode($batch->failed_job_ids, true),
  303. $this->unserialize($batch->options),
  304. CarbonImmutable::createFromTimestamp($batch->created_at),
  305. $batch->cancelled_at ? CarbonImmutable::createFromTimestamp($batch->cancelled_at) : $batch->cancelled_at,
  306. $batch->finished_at ? CarbonImmutable::createFromTimestamp($batch->finished_at) : $batch->finished_at
  307. );
  308. }
  309. }