feat: bring the plugin up to the current framework - #2
Conversation
Rebased onto #1, which moved the plugin to Tempest 3 and the current Plugin contract. What remained was the parts that still could not work. ragnarok/fenrir was still required and Registry still implemented its Extension, so registerExtension() was handed something the current library's signature does not accept. The plugin no longer registers an extension at all: registerExtension() calls initialize() immediately, so routing through it bought indirection and no ordering. The registry is started from the plugin's own boot instead. composer.json pinned tempcord/framework ^0.7, which under Composer's reading of a 0.x caret excludes the 0.10 the plugin is meant to extend, and carried a hardcoded version, which is the thing we took out of the other repos so Packagist reads tags. #[Task] now goes on an invokable class as well as a method, so a task that is one class reads like every other Tempcord attribute. Tasks compile to a TaskDefinition rather than the attribute being handed a reflector and passed around. An attribute that mutates cannot survive the discovery cache. Each turn runs in a fiber, so a task may await the REST API — which for a Discord bot is most of what a task wants to do. A turn is skipped while the previous one is still running, and a task that throws is logged and keeps its place instead of cancelling its own timer. Two cron bugs: a step over a range counted from the bottom of the field, so 1-10/2 gave 2,4,6,8,10 rather than 1,3,5,7,9; and restricting both day fields meant "and" where cron means "or", so 0 0 1 * 1 ran only on Mondays that fell on the first. Cron tasks are armed for the exact wait until the next matching minute rather than waking every minute, which drifts until a matching minute is stepped over entirely. An ordinary turn logs at debug: a task running every ten seconds was writing eight thousand info lines a day to say nothing happened. 67 tests driving a fake loop, phpstan at the level the framework uses, and the CI, release and contribution setup the other three repos have.
78fca60 to
3f54b8a
Compare
|
Rebased onto
Also added the CI, release and contribution setup the other three repos have: tests, static analysis, PR-title lint, semantic-release on One thing needs your call before merging: this repo has no tags. semantic-release with no tag to start from will cut |
|
🎉 This PR is included in version 1.0.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
The plugin was written against framework
0.6and does not load against0.10. Everything it reached for on the framework side has since moved:Tempcord\Contract\CanBeHandledTempcord\Support\Commands\CommandHandlerTempcord\Plugins\IsPluginPlugin::boot()TempcordinstanceRagnarok\Fenrir\DiscordTempcord\Discord\DiscordTempest\getTempest\Container\getcomposer.jsonalso pinnedtempest/* ^2against a framework on^3.18, and carried a hardcoded"version": "0.5.0"— the same thing we took out of the other repos so Packagist reads tags instead.#[Task]now goes on a class or a methodPer the discussion: on an invokable class it reads like every other Tempcord attribute, where a task is one class; on a method it still groups several chores that genuinely belong together.
Attributes stopped carrying state
Tasks compile to a
TaskDefinitioninstead of the attribute being handed a reflector viasetReflector()and passed around. An attribute that mutates cannot survive the discovery cache — which is what the oldcreateCachePayload()was working around, by serializing the wholeRegistryand thenforeach-ing the unserialized object as if it were a list. That path was a fatal the first time it ran.Each turn runs in a fiber
invoke()was called synchronously, so no task couldawaitthe REST API — for a Discord bot that is most of what a scheduled task wants to do. Turns now run the way command handlers do. Alongside that: a turn is skipped while the previous one is still running, and a task that throws is logged and keeps its place rather than cancelling its own timer and silently never running again.Two cron bugs
1-10/2gave2,4,6,8,10instead of1,3,5,7,9. The README documents1-10/2as a supported form.0 0 1 * 1ran only on Mondays that happened to fall on the first — roughly once a year instead of thirteen times.Cron tasks are also armed for the exact wait until the next matching minute and re-armed from the turn just taken, rather than waking every 60s to ask whether it is time. The old arming drifts from whatever offset the bot started at, and once the drift crosses a boundary a matching minute is stepped over and the task silently does not run that hour.
Smaller things
debug. A task running every ten seconds was writing ~8,600infolines a day to say nothing happened.Task::$handlerwas a property hook returning$this->handler— reading it once would have overflowed the stack.Registry::getStats()returned theRunnerwhere an array was declared.ClassName/ClassName::method. A bare method name collides between classes, and two tasks sharing a name share their statistics and cannot be cancelled apart.Tests
53, where there were none, driving a fake loop so the suite does not wait out the schedules it exercises. phpstan at level 5, matching the framework.
Not done here, and worth a separate decision: this repo has no CI and no release workflow, unlike the other three.
🤖 Generated with Claude Code