Persist material consumption snapshots
This commit is contained in:
@@ -112,7 +112,8 @@ def test_repeated_sequential_polls_and_long_cycle():
|
||||
output = io.StringIO()
|
||||
service = Mock(poll_once=Mock(side_effect=poll))
|
||||
MaterialPollingRunner(
|
||||
service, machine_id='machine', poll_interval_seconds=10,
|
||||
service, calculation_id='test-calculation', snapshot_writer=Mock(),
|
||||
machine_id='machine', poll_interval_seconds=10,
|
||||
clock=lambda: NOW + timedelta(seconds=elapsed), sleep=sleep, stdout=output,
|
||||
).run()
|
||||
assert events == ['poll-start', 'poll-end', ('sleep', 10)] * 2
|
||||
@@ -128,7 +129,8 @@ def test_error_then_success_preserves_opaque_order_and_reports_totals():
|
||||
output, errors = io.StringIO(), io.StringIO()
|
||||
sleep = Mock(side_effect=[None, KeyboardInterrupt])
|
||||
MaterialPollingRunner(
|
||||
service, machine_id='machine', poll_interval_seconds=5, clock=lambda: NOW,
|
||||
service, calculation_id='test-calculation', snapshot_writer=Mock(),
|
||||
machine_id='machine', poll_interval_seconds=5, clock=lambda: NOW,
|
||||
sleep=sleep, stdout=output, stderr=errors,
|
||||
).run()
|
||||
assert service.poll_once.call_count == 2
|
||||
@@ -143,7 +145,8 @@ def test_error_then_success_preserves_opaque_order_and_reports_totals():
|
||||
def test_interrupt_during_poll():
|
||||
sleep, output = Mock(), io.StringIO()
|
||||
MaterialPollingRunner(
|
||||
Mock(poll_once=Mock(side_effect=KeyboardInterrupt)), machine_id='m',
|
||||
Mock(poll_once=Mock(side_effect=KeyboardInterrupt)),
|
||||
calculation_id='test-calculation', snapshot_writer=Mock(), machine_id='m',
|
||||
poll_interval_seconds=1, sleep=sleep, stdout=output,
|
||||
).run()
|
||||
sleep.assert_not_called()
|
||||
@@ -154,6 +157,7 @@ def test_cycle_configuration_failure_is_fatal():
|
||||
sleep = Mock()
|
||||
runner = MaterialPollingRunner(
|
||||
Mock(poll_once=Mock(side_effect=ConfigurationError('bad settings'))),
|
||||
calculation_id='test-calculation', snapshot_writer=Mock(),
|
||||
machine_id='m', poll_interval_seconds=1, sleep=sleep,
|
||||
)
|
||||
with pytest.raises(ConfigurationError):
|
||||
@@ -164,7 +168,10 @@ def test_cycle_configuration_failure_is_fatal():
|
||||
@pytest.mark.parametrize('interval', [0, -1, float('nan'), float('inf'), True])
|
||||
def test_invalid_interval(interval):
|
||||
with pytest.raises(CalculationConfigError):
|
||||
MaterialPollingRunner(Mock(), machine_id='m', poll_interval_seconds=interval)
|
||||
MaterialPollingRunner(
|
||||
Mock(), machine_id='m', calculation_id='test', snapshot_writer=Mock(),
|
||||
poll_interval_seconds=interval,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('operation', ['load', 'save'])
|
||||
@@ -182,7 +189,10 @@ def test_state_error_classification(operation):
|
||||
def test_runtime_wiring(tmp_path, monkeypatch):
|
||||
monkeypatch.setenv('ENLYZE_BASE_URL', 'https://example.invalid/api/')
|
||||
secrets = tmp_path / 'secret.env'
|
||||
secrets.write_text('ENLYZE_API_KEY=secret-from-file\n')
|
||||
for key, value in dict(HOST='localhost', PORT='5432', DB='analytics',
|
||||
USER='user', PASSWORD='environment-password').items():
|
||||
monkeypatch.setenv(f'POSTGRES_{key}', value)
|
||||
secrets.write_text('ENLYZE_API_KEY=secret-from-file\nPOSTGRES_PASSWORD=file-password\n')
|
||||
with patch('production_analytics.service.material_runtime.MaterialPollingService') as service:
|
||||
runner = build_material_runner(
|
||||
load_material_calculation(EXAMPLE), poll_interval_seconds=7,
|
||||
@@ -198,6 +208,9 @@ def test_runtime_wiring(tmp_path, monkeypatch):
|
||||
assert kwargs['state_store'].store._directory == tmp_path / 'state'
|
||||
assert runner.service is service.return_value
|
||||
assert runner.interval == 7
|
||||
assert runner.calculation_id == 'k7-fiber-consumption'
|
||||
assert runner.snapshot_writer.settings.password == 'file-password'
|
||||
assert runner.snapshot_writer.settings.dbname == 'analytics'
|
||||
|
||||
|
||||
def test_cli_bad_config(tmp_path, capsys):
|
||||
@@ -257,7 +270,8 @@ def test_failed_cycle_keeps_checkpoint_and_recovers(tmp_path):
|
||||
raise KeyboardInterrupt
|
||||
|
||||
MaterialPollingRunner(
|
||||
service, machine_id='machine', poll_interval_seconds=1,
|
||||
service, calculation_id='test-calculation', snapshot_writer=Mock(),
|
||||
machine_id='machine', poll_interval_seconds=1,
|
||||
clock=lambda: NOW + timedelta(seconds=10), sleep=sleep,
|
||||
stdout=io.StringIO(), stderr=io.StringIO(),
|
||||
).run()
|
||||
|
||||
Reference in New Issue
Block a user