Skip to content

Refactor GoRouter refreshListenable to avoid per-second schedule tick redirects #524

Description

@jjoonleo

Problem

GoRouter.refreshListenable currently subscribes to ScheduleBloc.stream. During an active preparation session, ScheduleBloc emits a ScheduleTick update every second, so GoRouter can refresh and re-run redirect evaluation every second even though the global redirect logic does not read schedule progress.

This makes the router refresh path depend on high-frequency timer state and risks unnecessary route work during preparation.

Evidence

  • lib/presentation/app/go_router.dart wires scheduleBloc.stream into refreshListenable through StreamToListenable.
  • lib/core/utils/stream_to_listenable.dart calls notifyListeners() for every stream event.
  • lib/presentation/app/bloc/schedule/schedule_bloc.dart starts a Timer.periodic(Duration(seconds: 1), ...) and emits schedule progress on each tick.
  • The global redirect logic depends on auth, notification gate, alarm gate, and path; it does not need per-second schedule elapsed time.

Proposed direction

Remove raw scheduleBloc.stream from the router-level refreshListenable, or replace it with a filtered/listenable source that only notifies on schedule state transitions that routing actually needs.

If schedule-driven routing is required for specific flows, model that explicitly with a narrow signal such as status/id changes, not per-second preparation progress.

Acceptance criteria

  • GoRouter global redirects are not refreshed by every ScheduleTick during active preparation.
  • Auth, onboarding, notification permission, and alarm permission redirects still refresh immediately when their source states change.
  • Any schedule-dependent navigation remains covered by explicit bloc listeners or a filtered router refresh signal.
  • Add or update a focused test proving per-second schedule progress does not notify the router refresh listenable while relevant route-affecting state changes still do.

Source: Codex codebase audit on 2026-06-28.

Metadata

Metadata

Assignees

No one assigned

    Labels

    codex-readyCan be started independently by a Codex thread nowpriority: P2Medium priority production-readiness workproduction-readinessWork required before production releaserefactorschedulerelated to schedule feature

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions