Summary
Introduce a small Scheduler abstraction that fires a task on a periodic tick, decoupling recurring background work from real wall-clock time. Provide two implementations: a real wall-clock scheduler backed by a ScheduledExecutorService, and a deterministic scheduler whose ticks are driven explicitly so time-based logic can be unit-tested without sleeping.
Motivation: Aspnes & Shah, "Skip Graphs" (arXiv:cs/0306043), Algorithm 8 (Section 5.2.1), specifies a periodic backpointer-repair / self-stabilization procedure that each node runs on a recurring interval to restore neighbor-link consistency. Testing such a sweep deterministically requires advancing "time" explicitly rather than sleeping on the wall clock. This scheduler interface is that seam.
This issue delivers only the scheduling primitive and its tests. Implementing an actual repair sweep, and wiring a scheduler into SkipNode, are out of scope and are not touched here.
Scope
src/main/java/scheduler/Scheduler.java (new) — interface for a periodic tick. Defines a method to start a recurring Runnable task at a fixed period, and a method to stop it and release resources. Javadoc states the contract: at most one active task per scheduler, stop() is idempotent, and thread-safety expectations.
src/main/java/scheduler/WallClockScheduler.java (new) — real implementation backed by a single-threaded ScheduledExecutorService using scheduleAtFixedRate; stop() shuts the executor down cleanly and is safe to call more than once.
src/main/java/scheduler/ManualScheduler.java (new) — deterministic implementation (test double). Records the registered task and exposes an explicit tick() (fire once) plus an advance-by-N helper that invokes the task synchronously on the calling thread, using no real time and no threads; after stop(), further ticks are no-ops.
src/test/java/scheduler/ManualSchedulerTest.java (new) — JUnit 5 unit test covering the deterministic double.
Note: the deterministic implementation is placed under src/main/java (not src/test) so that both future production code paths and tests can depend on it.
Acceptance Criteria
Dependencies
None. This is a self-contained primitive: it adds new files under a new scheduler package and does not modify any existing class.
Part of #33. Depends on: none — ready to start
Summary
Introduce a small
Schedulerabstraction that fires a task on a periodic tick, decoupling recurring background work from real wall-clock time. Provide two implementations: a real wall-clock scheduler backed by aScheduledExecutorService, and a deterministic scheduler whose ticks are driven explicitly so time-based logic can be unit-tested without sleeping.Motivation: Aspnes & Shah, "Skip Graphs" (arXiv:cs/0306043), Algorithm 8 (Section 5.2.1), specifies a periodic backpointer-repair / self-stabilization procedure that each node runs on a recurring interval to restore neighbor-link consistency. Testing such a sweep deterministically requires advancing "time" explicitly rather than sleeping on the wall clock. This scheduler interface is that seam.
This issue delivers only the scheduling primitive and its tests. Implementing an actual repair sweep, and wiring a scheduler into
SkipNode, are out of scope and are not touched here.Scope
src/main/java/scheduler/Scheduler.java(new) — interface for a periodic tick. Defines a method to start a recurringRunnabletask at a fixed period, and a method to stop it and release resources. Javadoc states the contract: at most one active task per scheduler,stop()is idempotent, and thread-safety expectations.src/main/java/scheduler/WallClockScheduler.java(new) — real implementation backed by a single-threadedScheduledExecutorServiceusingscheduleAtFixedRate;stop()shuts the executor down cleanly and is safe to call more than once.src/main/java/scheduler/ManualScheduler.java(new) — deterministic implementation (test double). Records the registered task and exposes an explicittick()(fire once) plus an advance-by-N helper that invokes the task synchronously on the calling thread, using no real time and no threads; afterstop(), further ticks are no-ops.src/test/java/scheduler/ManualSchedulerTest.java(new) — JUnit 5 unit test covering the deterministic double.Note: the deterministic implementation is placed under
src/main/java(notsrc/test) so that both future production code paths and tests can depend on it.Acceptance Criteria
Scheduleris an interface defining a start(task, period) operation and astop()operation; every public member carries Javadoc (@param/@return) that satisfies checkstyle.WallClockSchedulerruns the supplied task at the configured fixed period via aScheduledExecutorService;stop()shuts the executor down and is safe to call repeatedly.ManualScheduleruses no wall-clock time and no background threads; each tick fires the registered task synchronously on the calling thread; afterstop(), additional tick calls do not invoke the task.ManualSchedulerTestasserts: N ticks invoke the task exactly N times; the task is not invoked before the first tick; afterstop(), further ticks do not invoke the task. The test contains noThread.sleepand no wall-clock waiting.SkipNodeor any existing class.mvn testpasses and checkstyle passes. Total change (production + tests) is <= 200 lines.Dependencies
None. This is a self-contained primitive: it adds new files under a new
schedulerpackage and does not modify any existing class.Part of #33. Depends on: none — ready to start