Skip to content

Feature request: configurable housekeeping (Transport::jobs()) interval #83

Description

@mclueppers

The problem being solved

Reticulum::loop() only runs Transport::jobs() once Type::Reticulum::JOB_INTERVAL (60 s in Type.h) has elapsed since the previous pass. That pass is where the time-sensitive transport work lives:

  • retransmission of announces held in _announce_table — i.e. forwarding an announce received on one interface to the others, which is the core job of a transport node;
  • link and pending-link timeouts, including expiring the path and re-requesting it when a link never activates;
  • resource watchdogs on active links (retransmit/timeout of dropped parts);
  • packet-receipt timeouts and culling.

With a 60 s cadence every one of these waits up to a minute. The reference Python implementation runs the equivalent Transport.jobs() every 0.25 s.

Observed on an ESP32-S3 node (microReticulum 0.5.0, Arduino core 2.0.17 / ESP-IDF 4.4.7, Transport enabled, one LoRa and one TCP interface, loop() called continuously from a dedicated FreeRTOS task): an announce arriving on one interface was forwarded on the other anywhere between 0 and 60 s later depending on where in the interval it landed, and link setups from a phone client across the node showed the same latency on the timeout/retry path.

Why existing functionality is insufficient

The interval is a compile-time constant with no API to change it. The only workaround is for the application to call Transport::jobs() itself on its own schedule, which duplicates what loop() already does, relies on knowledge of library internals, and — since loop() keeps its own _jobs_last_run — still leaves the library's pass running on top of it.

Proposed solution

Expose the interval as a runtime setting on Reticulum, defaulting to the current JOB_INTERVAL so nothing changes unless an application opts in:

// seconds; default Type::Reticulum::JOB_INTERVAL (60)
static float Reticulum::jobs_interval();
static void  Reticulum::jobs_interval(float seconds);

loop() compares against the configured value instead of the constant. An application that needs prompt propagation sets it once at startup, e.g. RNS::Reticulum::jobs_interval(1.0f);. 1 s has been running for hours on an ESP32-S3 with no measurable load increase; announces now cross the node in ≤ 1 s.

Possible alternatives

  • Lower JOB_INTERVAL itself (to 1 s, or 0.25 s like RNS). Simpler, but it changes behaviour for every existing user and the right value depends on the platform's budget — better handled as a separate decision once the knob exists.
  • Run the announce-retransmit part of jobs() on every loop() and keep the slower cadence for the culling work. Better latency for the common case, but a larger change to Transport and harder to reason about.
  • Leave it to applications to call Transport::jobs() (status quo) — see above.

Expected impact on existing users

None unless the setter is called; the default remains 60 s.

Compatibility concerns

Additive API only (one getter, one setter, one static member); no protocol, storage or configuration-format changes. The JOB_INTERVAL constant stays in place for anything that references it.

I have a small, focused PR ready (tested on ESP32-S3; native build unaffected) and will link it to this issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions