mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-07-24 18:58:12 +00:00
fix: db compaction run (#1156)
These fixes were taken from https://github.com/arneman/EOS/tree/refactor/economic-objective. 1. Fix compaction job registration bug in eos.py: - compact_eos_database was registered with save_eos_database function - Now correctly calls compact_eos_database() - Root cause: compaction/vacuum never ran, allowing records to grow unbounded 2. Optimize db_iterate_records() from O(n) to O(log n): - Previous: linear scan from index 0 for every key_to_array() call - Now: uses bisect_left on _db_sorted_timestamps to skip to start position - Critical for large datasets: 9400 measurement records → 94s/call overhead → 5 calls/optimization 3. Reduce compaction_interval_sec default from 604800s (7 days) to 3600s (1 hour): - With 7-day interval: 65000 records accumulate before first cleanup - Bridge pushes ~1 record/9s (grid_export_emr) - Hourly compaction + 2h data window → stable ~950 records Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
@@ -109,7 +109,7 @@ class DatabaseCommonSettings(SettingsBaseModel):
|
||||
)
|
||||
|
||||
compaction_interval_sec: Optional[int] = Field(
|
||||
default=7 * 24 * 3600, # weekly
|
||||
default=3600, # hourly
|
||||
ge=0,
|
||||
json_schema_extra={
|
||||
"description": (
|
||||
@@ -117,7 +117,7 @@ class DatabaseCommonSettings(SettingsBaseModel):
|
||||
"Compaction downsamples old records to reduce storage while retaining "
|
||||
"coverage. Set to None to disable automatic compaction."
|
||||
),
|
||||
"examples": [604800], # 1 week
|
||||
"examples": [3600], # 1 hour
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -1603,7 +1603,14 @@ class DatabaseRecordProtocolMixin(
|
||||
end_timestamp=end_timestamp,
|
||||
)
|
||||
|
||||
for record in self.records:
|
||||
# Use bisect to find the first record at or after start_timestamp.
|
||||
# _db_sorted_timestamps and self.records are always kept in parallel
|
||||
# (same insertion index), so bisect_left gives the correct slice start.
|
||||
start_idx = 0
|
||||
if start_timestamp and not isinstance(start_timestamp, _DatabaseTimestampUnbound):
|
||||
start_idx = bisect.bisect_left(self._db_sorted_timestamps, start_timestamp)
|
||||
|
||||
for record in self.records[start_idx:]:
|
||||
record_date_time_timestamp = DatabaseTimestamp.from_datetime(record.date_time)
|
||||
|
||||
if start_timestamp and record_date_time_timestamp < start_timestamp:
|
||||
@@ -1702,7 +1709,7 @@ class DatabaseRecordProtocolMixin(
|
||||
f"Vacuum requested for database '{self.db_namespace()}' but keep limit is infinite."
|
||||
)
|
||||
return 0
|
||||
keep_hours = keep_duration.hours
|
||||
keep_hours = int(keep_duration.total_seconds() // 3600)
|
||||
|
||||
if keep_hours is not None:
|
||||
_, db_max = await self.db_timestamp_range()
|
||||
|
||||
@@ -184,7 +184,9 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||
"save_eos_database", save_eos_database, interval_attr="database/autosave_interval_sec"
|
||||
)
|
||||
manager.register(
|
||||
"compact_eos_database", save_eos_database, interval_attr="database/compaction_interval_sec"
|
||||
"compact_eos_database",
|
||||
compact_eos_database,
|
||||
interval_attr="database/compaction_interval_sec",
|
||||
)
|
||||
manager.register("manage_energy", ems_manage_energy, interval_attr="ems/interval")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user