Skip to content

Releases: elixir-lang/expert

nightly: refactor: make progress tracking better follow LSP semantics (#260)

29 Dec 00:28
a411229

Choose a tag to compare

This pull request overhauls the way progress reporting is handled in Expert. The top-level API remains largely the same for callers.

The prior architecture started a per-project stateful GenServer that handled progress tracking logic internally:
* It was difficult to reason about due to the depth and statefulness of the call stack.
    * Or at least, I found it difficult. YMMV, but my brain works better with shallow call stacks.
* The Progress GenServers were initiated per-project, even though workDoneTokens aren’t scoped as such in LSP.
* Had no means to handle client-initiated workDoneTokens
    * I had a `with_client_progress` function incorporated here, but I removed it for the sake of review. There’s already a lot here.
* Had no means to deallocate workDoneTokens should they be cancel-able.
    * Requests for long-running tasks can be canceled by the client, in which case it cancels the request by ID, but not any workDoneTokens associated.
        * Hence why the work-done-tokens now live in the caller’s context.

The new progress reporting modules are organized as follows:
* `Forge.Progress` - a behaviour that defines the `with_progress` and `with_tracked_progress` helper functions, permitting the implementing module provides the following functions:
    * `begin/2`
    * `report/2`
    * `complete/2`
* `Expert.Progress` - a process-less module that directly handles progress reporting, implements the aforementioned
* `Engine.Progress` - a thin wrapper that calls `Expert.Progress` via erpc.
* `Forge.Progress.Tracker` - An ephemeral GenServer for reporting progress between concurrently running tasks.
    * Supports straight percentage reporting by default, or custom callbacks like `turbo-encabulating files: 3/25` should that be preferable.

All in all: Less processes, more sequential Elixir, more flexibility, better alignment with LSP semantics.

Some additional changes:
* Make tests that wait the `project_compiled` message less flaky by increasing the timeout from 100ms -> 5s.
* Debounce namespacing logs
* When the engine starts, store its manager name in a persistent term and use that, instead of building it.