Completed
Pull Request — master (#4253)
by Morris
14:01 queued 01:59
created
lib/private/BackgroundJob/JobList.php 1 patch
Indentation   +281 added lines, -281 removed lines patch added patch discarded remove patch
@@ -36,285 +36,285 @@
 block discarded – undo
36 36
 
37 37
 class JobList implements IJobList {
38 38
 
39
-	/** @var IDBConnection */
40
-	protected $connection;
41
-
42
-	/**@var IConfig */
43
-	protected $config;
44
-
45
-	/**@var ITimeFactory */
46
-	protected $timeFactory;
47
-
48
-	/**
49
-	 * @param IDBConnection $connection
50
-	 * @param IConfig $config
51
-	 * @param ITimeFactory $timeFactory
52
-	 */
53
-	public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) {
54
-		$this->connection = $connection;
55
-		$this->config = $config;
56
-		$this->timeFactory = $timeFactory;
57
-	}
58
-
59
-	/**
60
-	 * @param IJob|string $job
61
-	 * @param mixed $argument
62
-	 */
63
-	public function add($job, $argument = null) {
64
-		if (!$this->has($job, $argument)) {
65
-			if ($job instanceof IJob) {
66
-				$class = get_class($job);
67
-			} else {
68
-				$class = $job;
69
-			}
70
-
71
-			$argument = json_encode($argument);
72
-			if (strlen($argument) > 4000) {
73
-				throw new \InvalidArgumentException('Background job arguments can\'t exceed 4000 characters (json encoded)');
74
-			}
75
-
76
-			$query = $this->connection->getQueryBuilder();
77
-			$query->insert('jobs')
78
-				->values([
79
-					'class' => $query->createNamedParameter($class),
80
-					'argument' => $query->createNamedParameter($argument),
81
-					'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
82
-					'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT),
83
-				]);
84
-			$query->execute();
85
-		}
86
-	}
87
-
88
-	/**
89
-	 * @param IJob|string $job
90
-	 * @param mixed $argument
91
-	 */
92
-	public function remove($job, $argument = null) {
93
-		if ($job instanceof IJob) {
94
-			$class = get_class($job);
95
-		} else {
96
-			$class = $job;
97
-		}
98
-
99
-		$query = $this->connection->getQueryBuilder();
100
-		$query->delete('jobs')
101
-			->where($query->expr()->eq('class', $query->createNamedParameter($class)));
102
-		if (!is_null($argument)) {
103
-			$argument = json_encode($argument);
104
-			$query->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)));
105
-		}
106
-		$query->execute();
107
-	}
108
-
109
-	/**
110
-	 * @param int $id
111
-	 */
112
-	protected function removeById($id) {
113
-		$query = $this->connection->getQueryBuilder();
114
-		$query->delete('jobs')
115
-			->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
116
-		$query->execute();
117
-	}
118
-
119
-	/**
120
-	 * check if a job is in the list
121
-	 *
122
-	 * @param IJob|string $job
123
-	 * @param mixed $argument
124
-	 * @return bool
125
-	 */
126
-	public function has($job, $argument) {
127
-		if ($job instanceof IJob) {
128
-			$class = get_class($job);
129
-		} else {
130
-			$class = $job;
131
-		}
132
-		$argument = json_encode($argument);
133
-
134
-		$query = $this->connection->getQueryBuilder();
135
-		$query->select('id')
136
-			->from('jobs')
137
-			->where($query->expr()->eq('class', $query->createNamedParameter($class)))
138
-			->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)))
139
-			->setMaxResults(1);
140
-
141
-		$result = $query->execute();
142
-		$row = $result->fetch();
143
-		$result->closeCursor();
144
-
145
-		return (bool) $row;
146
-	}
147
-
148
-	/**
149
-	 * get all jobs in the list
150
-	 *
151
-	 * @return IJob[]
152
-	 * @deprecated 9.0.0 - This method is dangerous since it can cause load and
153
-	 * memory problems when creating too many instances.
154
-	 */
155
-	public function getAll() {
156
-		$query = $this->connection->getQueryBuilder();
157
-		$query->select('*')
158
-			->from('jobs');
159
-		$result = $query->execute();
160
-
161
-		$jobs = [];
162
-		while ($row = $result->fetch()) {
163
-			$job = $this->buildJob($row);
164
-			if ($job) {
165
-				$jobs[] = $job;
166
-			}
167
-		}
168
-		$result->closeCursor();
169
-
170
-		return $jobs;
171
-	}
172
-
173
-	/**
174
-	 * get the next job in the list
175
-	 *
176
-	 * @return IJob|null
177
-	 */
178
-	public function getNext() {
179
-		$query = $this->connection->getQueryBuilder();
180
-		$query->select('*')
181
-			->from('jobs')
182
-			->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT)))
183
-			->orderBy('last_checked', 'ASC')
184
-			->setMaxResults(1);
185
-
186
-		$update = $this->connection->getQueryBuilder();
187
-		$update->update('jobs')
188
-			->set('reserved_at', $update->createNamedParameter($this->timeFactory->getTime()))
189
-			->set('last_checked', $update->createNamedParameter($this->timeFactory->getTime()))
190
-			->where($update->expr()->eq('id', $update->createParameter('jobid')))
191
-			->andWhere($update->expr()->eq('reserved_at', $update->createParameter('reserved_at')))
192
-			->andWhere($update->expr()->eq('last_checked', $update->createParameter('last_checked')));
193
-
194
-		$result = $query->execute();
195
-		$row = $result->fetch();
196
-		$result->closeCursor();
197
-
198
-		if ($row) {
199
-			$update->setParameter('jobid', $row['id']);
200
-			$update->setParameter('reserved_at', $row['reserved_at']);
201
-			$update->setParameter('last_checked', $row['last_checked']);
202
-			$count = $update->execute();
203
-
204
-			if ($count === 0) {
205
-				// Background job already executed elsewhere, try again.
206
-				return $this->getNext();
207
-			}
208
-			$job = $this->buildJob($row);
209
-
210
-			if ($job === null) {
211
-				// Background job from disabled app, try again.
212
-				return $this->getNext();
213
-			}
214
-
215
-			return $job;
216
-		} else {
217
-			return null;
218
-		}
219
-	}
220
-
221
-	/**
222
-	 * @param int $id
223
-	 * @return IJob|null
224
-	 */
225
-	public function getById($id) {
226
-		$query = $this->connection->getQueryBuilder();
227
-		$query->select('*')
228
-			->from('jobs')
229
-			->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
230
-		$result = $query->execute();
231
-		$row = $result->fetch();
232
-		$result->closeCursor();
233
-
234
-		if ($row) {
235
-			return $this->buildJob($row);
236
-		} else {
237
-			return null;
238
-		}
239
-	}
240
-
241
-	/**
242
-	 * get the job object from a row in the db
243
-	 *
244
-	 * @param array $row
245
-	 * @return IJob|null
246
-	 */
247
-	private function buildJob($row) {
248
-		try {
249
-			try {
250
-				// Try to load the job as a service
251
-				/** @var IJob $job */
252
-				$job = \OC::$server->query($row['class']);
253
-			} catch (QueryException $e) {
254
-				if (class_exists($row['class'])) {
255
-					$class = $row['class'];
256
-					$job = new $class();
257
-				} else {
258
-					// job from disabled app or old version of an app, no need to do anything
259
-					return null;
260
-				}
261
-			}
262
-
263
-			$job->setId($row['id']);
264
-			$job->setLastRun($row['last_run']);
265
-			$job->setArgument(json_decode($row['argument'], true));
266
-			return $job;
267
-		} catch (AutoloadNotAllowedException $e) {
268
-			// job is from a disabled app, ignore
269
-			return null;
270
-		}
271
-	}
272
-
273
-	/**
274
-	 * set the job that was last ran
275
-	 *
276
-	 * @param IJob $job
277
-	 */
278
-	public function setLastJob($job) {
279
-		$this->unlockJob($job);
280
-		$this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
281
-	}
282
-
283
-	/**
284
-	 * Remove the reservation for a job
285
-	 *
286
-	 * @param IJob $job
287
-	 */
288
-	public function unlockJob($job) {
289
-		$query = $this->connection->getQueryBuilder();
290
-		$query->update('jobs')
291
-			->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
292
-			->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
293
-		$query->execute();
294
-	}
295
-
296
-	/**
297
-	 * get the id of the last ran job
298
-	 *
299
-	 * @return int
300
-	 * @deprecated 9.1.0 - The functionality behind the value is deprecated, it
301
-	 *    only tells you which job finished last, but since we now allow multiple
302
-	 *    executors to run in parallel, it's not used to calculate the next job.
303
-	 */
304
-	public function getLastJob() {
305
-		return (int) $this->config->getAppValue('backgroundjob', 'lastjob', 0);
306
-	}
307
-
308
-	/**
309
-	 * set the lastRun of $job to now
310
-	 *
311
-	 * @param IJob $job
312
-	 */
313
-	public function setLastRun($job) {
314
-		$query = $this->connection->getQueryBuilder();
315
-		$query->update('jobs')
316
-			->set('last_run', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
317
-			->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
318
-		$query->execute();
319
-	}
39
+    /** @var IDBConnection */
40
+    protected $connection;
41
+
42
+    /**@var IConfig */
43
+    protected $config;
44
+
45
+    /**@var ITimeFactory */
46
+    protected $timeFactory;
47
+
48
+    /**
49
+     * @param IDBConnection $connection
50
+     * @param IConfig $config
51
+     * @param ITimeFactory $timeFactory
52
+     */
53
+    public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) {
54
+        $this->connection = $connection;
55
+        $this->config = $config;
56
+        $this->timeFactory = $timeFactory;
57
+    }
58
+
59
+    /**
60
+     * @param IJob|string $job
61
+     * @param mixed $argument
62
+     */
63
+    public function add($job, $argument = null) {
64
+        if (!$this->has($job, $argument)) {
65
+            if ($job instanceof IJob) {
66
+                $class = get_class($job);
67
+            } else {
68
+                $class = $job;
69
+            }
70
+
71
+            $argument = json_encode($argument);
72
+            if (strlen($argument) > 4000) {
73
+                throw new \InvalidArgumentException('Background job arguments can\'t exceed 4000 characters (json encoded)');
74
+            }
75
+
76
+            $query = $this->connection->getQueryBuilder();
77
+            $query->insert('jobs')
78
+                ->values([
79
+                    'class' => $query->createNamedParameter($class),
80
+                    'argument' => $query->createNamedParameter($argument),
81
+                    'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
82
+                    'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT),
83
+                ]);
84
+            $query->execute();
85
+        }
86
+    }
87
+
88
+    /**
89
+     * @param IJob|string $job
90
+     * @param mixed $argument
91
+     */
92
+    public function remove($job, $argument = null) {
93
+        if ($job instanceof IJob) {
94
+            $class = get_class($job);
95
+        } else {
96
+            $class = $job;
97
+        }
98
+
99
+        $query = $this->connection->getQueryBuilder();
100
+        $query->delete('jobs')
101
+            ->where($query->expr()->eq('class', $query->createNamedParameter($class)));
102
+        if (!is_null($argument)) {
103
+            $argument = json_encode($argument);
104
+            $query->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)));
105
+        }
106
+        $query->execute();
107
+    }
108
+
109
+    /**
110
+     * @param int $id
111
+     */
112
+    protected function removeById($id) {
113
+        $query = $this->connection->getQueryBuilder();
114
+        $query->delete('jobs')
115
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
116
+        $query->execute();
117
+    }
118
+
119
+    /**
120
+     * check if a job is in the list
121
+     *
122
+     * @param IJob|string $job
123
+     * @param mixed $argument
124
+     * @return bool
125
+     */
126
+    public function has($job, $argument) {
127
+        if ($job instanceof IJob) {
128
+            $class = get_class($job);
129
+        } else {
130
+            $class = $job;
131
+        }
132
+        $argument = json_encode($argument);
133
+
134
+        $query = $this->connection->getQueryBuilder();
135
+        $query->select('id')
136
+            ->from('jobs')
137
+            ->where($query->expr()->eq('class', $query->createNamedParameter($class)))
138
+            ->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)))
139
+            ->setMaxResults(1);
140
+
141
+        $result = $query->execute();
142
+        $row = $result->fetch();
143
+        $result->closeCursor();
144
+
145
+        return (bool) $row;
146
+    }
147
+
148
+    /**
149
+     * get all jobs in the list
150
+     *
151
+     * @return IJob[]
152
+     * @deprecated 9.0.0 - This method is dangerous since it can cause load and
153
+     * memory problems when creating too many instances.
154
+     */
155
+    public function getAll() {
156
+        $query = $this->connection->getQueryBuilder();
157
+        $query->select('*')
158
+            ->from('jobs');
159
+        $result = $query->execute();
160
+
161
+        $jobs = [];
162
+        while ($row = $result->fetch()) {
163
+            $job = $this->buildJob($row);
164
+            if ($job) {
165
+                $jobs[] = $job;
166
+            }
167
+        }
168
+        $result->closeCursor();
169
+
170
+        return $jobs;
171
+    }
172
+
173
+    /**
174
+     * get the next job in the list
175
+     *
176
+     * @return IJob|null
177
+     */
178
+    public function getNext() {
179
+        $query = $this->connection->getQueryBuilder();
180
+        $query->select('*')
181
+            ->from('jobs')
182
+            ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - 12 * 3600, IQueryBuilder::PARAM_INT)))
183
+            ->orderBy('last_checked', 'ASC')
184
+            ->setMaxResults(1);
185
+
186
+        $update = $this->connection->getQueryBuilder();
187
+        $update->update('jobs')
188
+            ->set('reserved_at', $update->createNamedParameter($this->timeFactory->getTime()))
189
+            ->set('last_checked', $update->createNamedParameter($this->timeFactory->getTime()))
190
+            ->where($update->expr()->eq('id', $update->createParameter('jobid')))
191
+            ->andWhere($update->expr()->eq('reserved_at', $update->createParameter('reserved_at')))
192
+            ->andWhere($update->expr()->eq('last_checked', $update->createParameter('last_checked')));
193
+
194
+        $result = $query->execute();
195
+        $row = $result->fetch();
196
+        $result->closeCursor();
197
+
198
+        if ($row) {
199
+            $update->setParameter('jobid', $row['id']);
200
+            $update->setParameter('reserved_at', $row['reserved_at']);
201
+            $update->setParameter('last_checked', $row['last_checked']);
202
+            $count = $update->execute();
203
+
204
+            if ($count === 0) {
205
+                // Background job already executed elsewhere, try again.
206
+                return $this->getNext();
207
+            }
208
+            $job = $this->buildJob($row);
209
+
210
+            if ($job === null) {
211
+                // Background job from disabled app, try again.
212
+                return $this->getNext();
213
+            }
214
+
215
+            return $job;
216
+        } else {
217
+            return null;
218
+        }
219
+    }
220
+
221
+    /**
222
+     * @param int $id
223
+     * @return IJob|null
224
+     */
225
+    public function getById($id) {
226
+        $query = $this->connection->getQueryBuilder();
227
+        $query->select('*')
228
+            ->from('jobs')
229
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
230
+        $result = $query->execute();
231
+        $row = $result->fetch();
232
+        $result->closeCursor();
233
+
234
+        if ($row) {
235
+            return $this->buildJob($row);
236
+        } else {
237
+            return null;
238
+        }
239
+    }
240
+
241
+    /**
242
+     * get the job object from a row in the db
243
+     *
244
+     * @param array $row
245
+     * @return IJob|null
246
+     */
247
+    private function buildJob($row) {
248
+        try {
249
+            try {
250
+                // Try to load the job as a service
251
+                /** @var IJob $job */
252
+                $job = \OC::$server->query($row['class']);
253
+            } catch (QueryException $e) {
254
+                if (class_exists($row['class'])) {
255
+                    $class = $row['class'];
256
+                    $job = new $class();
257
+                } else {
258
+                    // job from disabled app or old version of an app, no need to do anything
259
+                    return null;
260
+                }
261
+            }
262
+
263
+            $job->setId($row['id']);
264
+            $job->setLastRun($row['last_run']);
265
+            $job->setArgument(json_decode($row['argument'], true));
266
+            return $job;
267
+        } catch (AutoloadNotAllowedException $e) {
268
+            // job is from a disabled app, ignore
269
+            return null;
270
+        }
271
+    }
272
+
273
+    /**
274
+     * set the job that was last ran
275
+     *
276
+     * @param IJob $job
277
+     */
278
+    public function setLastJob($job) {
279
+        $this->unlockJob($job);
280
+        $this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
281
+    }
282
+
283
+    /**
284
+     * Remove the reservation for a job
285
+     *
286
+     * @param IJob $job
287
+     */
288
+    public function unlockJob($job) {
289
+        $query = $this->connection->getQueryBuilder();
290
+        $query->update('jobs')
291
+            ->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
292
+            ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
293
+        $query->execute();
294
+    }
295
+
296
+    /**
297
+     * get the id of the last ran job
298
+     *
299
+     * @return int
300
+     * @deprecated 9.1.0 - The functionality behind the value is deprecated, it
301
+     *    only tells you which job finished last, but since we now allow multiple
302
+     *    executors to run in parallel, it's not used to calculate the next job.
303
+     */
304
+    public function getLastJob() {
305
+        return (int) $this->config->getAppValue('backgroundjob', 'lastjob', 0);
306
+    }
307
+
308
+    /**
309
+     * set the lastRun of $job to now
310
+     *
311
+     * @param IJob $job
312
+     */
313
+    public function setLastRun($job) {
314
+        $query = $this->connection->getQueryBuilder();
315
+        $query->update('jobs')
316
+            ->set('last_run', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
317
+            ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
318
+        $query->execute();
319
+    }
320 320
 }
Please login to merge, or discard this patch.