Repository navigation
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #126 +/- ##
==========================================
+ Coverage 90.30% 90.50% +0.19%
==========================================
Files 68 70 +2
Lines 6068 6142 +74
Branches 758 762 +4
==========================================
+ Hits 5480 5559 +79
+ Misses 466 463 -3
+ Partials 122 120 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
adefabian
force-pushed
the
feature/configurable_solver
branch
from
October 16, 2026 10:57
e9fdee6 to
507feff
Compare
adefabian
marked this pull request as ready for review
October 16, 2026 11:34
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Impulse always builds
DefaultSolver.A customer who needs the engine to behave differently on
silver-shaped data has no supported way to plug that in.
This PR lets a customer register their own
QuerySolversubclass and select it withquery_engine.solver, with its own typed settings insolver_config. It mirrors the customMeasurementDBfrom #109, and both now share one name registry. The change is additive: if nothingis configured,
DefaultSolveris used, andDeltaSolver/KeyValueStoreSolverkeep working asdeprecated aliases. The one breaking change is stricter parsing of unknown keys (below).
Breaking change
Unknown keys are now rejected at the top level of the config and directly under
query_engine.solver_config.query_enginealready rejects them, since #109. A config with amisspelled or misplaced key, for example
"solver"outsidequery_engine, fails at load time withExtra inputs are not permittedinstead of being silently ignored. Without this, forgetting ormisplacing
solversilently ranDefaultSolverand dropped the custom solver's settings.Behaviour changes
query_engine.solveris now astrand accepts any registered name. Before, it was aSolversenum member.
Solversis now aStrEnum, so comparisons like== Solvers.DEFAULT_SOLVERstillwork, but
.valueon the field doesn't.solverormeasurement_dbname fails at load time on its own key(
query_engine.solver/query_engine.measurement_db), and the error lists the registered names.resolve_measurement_db()returns the sharedRegistration. Its class field is nowimpl_cls(was
db_cls).Changes
QuerySolver.from_config(ctx)build hook, taking aSolverBuildContext(Spark session,
solver_config, RAW-data flags) (solvers/query_solver.py).DefaultSolverimplements it and registers itself with both aliases. Its constructor is unchanged. The context
copies the
query_enginesettings a solver needs, rather than passing theQueryEngineconfig,because the query engine must not depend on the reporting layer.
register_solver(name, config_cls=SolverConfig, aliases=())/resolve_solver(
solvers/solver_registry.py). Both are built on a genericRegistry(
impulse_query_engine/registry.py), which the measurement-DB registry now uses too.solvername is checked against the registry, andsolver_configis validated with theconfig class the selected solver registered. Missing or invalid custom settings fail at load time
with
invalid settings for solver 'X': …(impulse_reporting/config/config_parser.py).SolverConfigandImpulseConfigforbid unknown keys (see Breaking change). Custom configclasses inherit this.
Report.create_solverresolves the name and callsfrom_config. In telemetry,built-in solvers keep their existing names and a custom solver is logged as
custom, so customerclass names aren't sent (
impulse_reporting/core/report.py).MeasurementDB.
impulse-analyze,impulse-configandimpulse-data-modelskills updated.impulse-data-modelskill now recommend a custom MeasurementDB, nota custom solver, for structural differences in the source data.
Test Plan
from_configsolver_config, including omitted, missing and invalid settingssolver, andsolveroutsidequery_engineReportbuilds a registered solver; telemetry keeps the built-in namescustom_solver_report_test.py): every solve goes through the selectedsolver and its typed setting reaches it;
DefaultSolveris unchanged by the registrationpytest tests/ -n auto)"DefaultSolver"and contain nokeys the stricter parsing rejects)
Checklist
This pull request and its description were written by Isaac.