Engine: fail-fast on missing engine, deduplicate lazy-init
- Dominant language
- Kotlin
- Stars
- 734
- Forks
- 51
- Avg merge
- 9h 52m
- Merged PRs (30d)
- 6
Description
Follow-up to #249. `defaultEngine` is now `@Volatile`, so the original visibility race is fixed, but a few concerns remain in `multik-core/.../api/Engine.kt`:
### Problems
- **No fail-fast.** If no engine is registered, the user only finds out when they first call `mk.math` / `mk.linalg` / `mk.stat` — not at `Multik` initialization. `EngineMultikException("The map of engines is empty...")` is thrown lazily from each getter.
- **Duplicated lazy-init triad.** The same `engine == null → loadEngine() → engine = defaultEngine` block is repeated in `getMath()`, `getLinAlg()`, `getStatistics()`, and `getDefaultEngine()`.
- **Benign but real race in `loadEngine()`.** The check-then-assign on `defaultEngine` is not atomic; two threads can both execute the resolve. Idempotent today, but fragile.
### Suggested direction
- Validate `enginesProvider` once at companion init and fail fast if empty (or document the lazy contract explicitly).
- Extract the engine-resolution logic into a single helper used by all getters.
- Consider `AtomicReference` with `compareAndSet` in `loadEngine()` to make the initialization properly atomic.
Contributor guide
Research direction
Start in multik-core/.../api/Engine.kt, reading the companion initialization and the getMath(), getLinAlg(), getStatistics(), getDefaultEngine(), and loadEngine() paths. Trace how enginesProvider and defaultEngine are used, then verify that missing engines fail at Multik initialization and that all getters share one resolution path with safe concurrent initialization.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- api
- Issue type
- Refactor
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100