+ /**
+ * Delay the push subscriber
+ *
+ * @param integer $id Subscriber ID
+ * @return void
+ * @throws \Exception
+ */
+ public static function delay(int $id)
+ {
+ $subscriber = DBA::selectFirst('push_subscriber', ['push', 'callback_url', 'renewed', 'nickname'], ['id' => $id]);
+ if (!DBA::isResult($subscriber)) {
+ return;
+ }
+
+ $retrial = $subscriber['push'];
+
+ if ($retrial > 14) {
+ // End subscriptions if they weren't renewed for more than two months
+ $days = round((time() - strtotime($subscriber['renewed'])) / (60 * 60 * 24));
+
+ if ($days > 60) {
+ DBA::update('push_subscriber', ['push' => -1, 'next_try' => DBA::NULL_DATETIME], ['id' => $id]);
+ Logger::info('Delivery error: Subscription ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' is marked as ended.');
+ } else {
+ DBA::update('push_subscriber', ['push' => 0, 'next_try' => DBA::NULL_DATETIME], ['id' => $id]);
+ Logger::info('Delivery error: Giving up ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' for now.');
+ }
+ } else {
+ // Calculate the delay until the next trial
+ $delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1));
+ $next = DateTimeFormat::utc('now + ' . $delay . ' seconds');
+
+ $retrial = $retrial + 1;
+
+ DBA::update('push_subscriber', ['push' => $retrial, 'next_try' => $next], ['id' => $id]);
+ Logger::info('Delivery error: Next try (' . $retrial . ') ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' at ' . $next);
+ }
+ }
+
+ /**
+ * Reset the push subscriber
+ *
+ * @param integer $id Subscriber ID
+ * @param string $last_update Date of last transmitted item
+ * @return void
+ * @throws \Exception
+ */
+ public static function reset(int $id, string $last_update)
+ {
+ $subscriber = DBA::selectFirst('push_subscriber', ['callback_url', 'nickname'], ['id' => $id]);
+ if (!DBA::isResult($subscriber)) {
+ return;
+ }
+
+ // set last_update to the 'created' date of the last item, and reset push=0
+ $fields = ['push' => 0, 'next_try' => DBA::NULL_DATETIME, 'last_update' => $last_update];
+ DBA::update('push_subscriber', $fields, ['id' => $id]);
+ Logger::info('Subscriber ' . $subscriber['callback_url'] . ' for ' . $subscriber['nickname'] . ' is marked as vital');
+
+ $parts = parse_url($subscriber['callback_url']);
+ unset($parts['path']);
+ $server_url = Network::unparseURL($parts);
+ $gsid = GServer::getID($server_url, true);
+ if (!empty($gsid)) {
+ GServer::setProtocol($gsid, Post\DeliveryData::OSTATUS);
+ }