Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion RssCloud/Subscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public function __construct(
* or when the lease is old enough that the cloud server has probably expired it.
*
* rssCloud has no lease negotiation — the server does not tell us how long the subscription
* lasts — so this is purely a local timer. The conventional expiry is around 24 hours.
* lasts — so this is purely a local timer. Subscriptions expire after 25 hours and are meant to
* be renewed every 24 (http://walkthrough.rsscloud.co/).
*
* @param RssCloudState $state
*/
Expand Down
2 changes: 1 addition & 1 deletion configure.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<div class="form-group">
<label class="group-name" for="renew_hours"><?= _t('ext.rsscloud.renew_hours') ?></label>
<div class="group-controls">
<input type="number" name="renew_hours" id="renew_hours" min="1" max="168"
<input type="number" name="renew_hours" id="renew_hours" min="1" max="<?= RssCloudExtension::MAX_RENEW_HOURS ?>"
value="<?= (int)($this->renewSeconds() / 3600) ?>" />
<p class="help"><?= _i('help') ?> <?= _t('ext.rsscloud.renew_hours.help') ?></p>
</div>
Expand Down
19 changes: 15 additions & 4 deletions extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@ final class RssCloudExtension extends Minz_Extension {
public const NAME = 'rssCloud';

/**
* rssCloud has no lease negotiation, and the protocol documentation does not state an expiry.
* The convention among implementations is around 24 hours, so renew slightly early — the same
* policy core applies to WebSub leases in `FreshRSS_Feed::pubSubHubbubPrepare()`.
* rssCloud has no lease negotiation: the `pleaseNotify` response carries no duration. The rule
* is documented instead — subscriptions expire after 25 hours and must be renewed every 24
* (http://walkthrough.rsscloud.co/). Renewing at 23 stays an hour inside that requirement and
* leaves two hours before expiry, which is the margin {@see self::MAX_SUBSCRIPTIONS_PER_RUN}
* eats into when many subscriptions fall due at once. Core applies the same renew-early policy
* to WebSub leases in `FreshRSS_Feed::pubSubHubbubPrepare()`.
*/
public const DEFAULT_RENEW_HOURS = 23;

/**
* Renewing later than the documented 24-hour rule cannot work: the subscription is already gone
* by 25 hours, so every larger value simply lets it lapse. Clamped on the read path rather than
* only in the form, so a hand-edited configuration cannot get past it either.
*/
public const MAX_RENEW_HOURS = 24;

/** How stale a cloud-covered resource may get before we poll it anyway, as a safety net. */
public const DEFAULT_MAX_STALENESS_HOURS = 24;

Expand Down Expand Up @@ -135,7 +145,8 @@ public function isPollingSkipped(): bool {
}

public function renewSeconds(): int {
return max(1, $this->getSystemConfigurationInt('renew_hours') ?? self::DEFAULT_RENEW_HOURS) * 3600;
$hours = $this->getSystemConfigurationInt('renew_hours') ?? self::DEFAULT_RENEW_HOURS;
return min(self::MAX_RENEW_HOURS, max(1, $hours)) * 3600;
}

public function maxStalenessSeconds(): int {
Expand Down
2 changes: 1 addition & 1 deletion i18n/en/ext.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
'regenerate_token' => 'Regenerate callback token',
'regenerate_token.help' => 'Changes the secret path segment of the callback. Existing subscriptions stop being delivered until they are renewed.',
'renew_hours' => 'Renew subscriptions after (hours)',
'renew_hours.help' => 'rssCloud does not negotiate a lease duration. Most servers expire subscriptions after about 24 hours, so renew slightly sooner than that.',
'renew_hours.help' => 'rssCloud does not negotiate a lease duration. Subscriptions expire after 25 hours and are meant to be renewed every 24, so the default of 23 leaves a margin. Anything above 24 would simply lapse, and is capped.',
'skip_polling' => 'Skip polling covered resources',
'skip_polling.help' => 'Stop polling a resource on a timer while its cloud subscription is healthy. It is still polled if it goes stale, or when refreshed individually.',
),
Expand Down