feat: migrate storage from JSON files to SQLite
Some checks failed
Lint & Test / test (push) Failing after 28s
Some checks failed
Lint & Test / test (push) Failing after 28s
Replace 22 individual JSON store files with a single SQLite database (data/ledgrab.db). All entity stores now use BaseSqliteStore backed by SQLite with WAL mode, write-through caching, and thread-safe access. - Add Database class with SQLite backup/restore API - Add BaseSqliteStore as drop-in replacement for BaseJsonStore - Convert all 16 entity stores to SQLite - Move global settings (MQTT, external URL, auto-backup) to SQLite settings table - Replace JSON backup/restore with SQLite snapshot backups (.db files) - Remove partial export/import feature (backend + frontend) - Update demo seed to write directly to SQLite - Add "Backup Now" button to settings UI - Remove StorageConfig file path fields (single database_file remains)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"""Gradient storage with built-in seeding.
|
||||
|
||||
Provides CRUD for gradient entities. On first run (empty/missing file),
|
||||
Provides CRUD for gradient entities. On first run (empty/missing data),
|
||||
seeds 8 built-in gradients matching the legacy hardcoded palettes.
|
||||
Built-in gradients are read-only and cannot be deleted or modified.
|
||||
"""
|
||||
@@ -9,7 +9,8 @@ import uuid
|
||||
from datetime import datetime, timezone
|
||||
from typing import List, Optional
|
||||
|
||||
from wled_controller.storage.base_store import BaseJsonStore
|
||||
from wled_controller.storage.base_sqlite_store import BaseSqliteStore
|
||||
from wled_controller.storage.database import Database
|
||||
from wled_controller.storage.gradient import Gradient
|
||||
from wled_controller.utils import get_logger
|
||||
|
||||
@@ -43,12 +44,12 @@ def _tuples_to_stops(tuples: list) -> list:
|
||||
return [{"position": t[0], "color": [t[1], t[2], t[3]]} for t in tuples]
|
||||
|
||||
|
||||
class GradientStore(BaseJsonStore[Gradient]):
|
||||
_json_key = "gradients"
|
||||
class GradientStore(BaseSqliteStore[Gradient]):
|
||||
_table_name = "gradients"
|
||||
_entity_name = "Gradient"
|
||||
|
||||
def __init__(self, file_path: str):
|
||||
super().__init__(file_path, Gradient.from_dict)
|
||||
def __init__(self, db: Database):
|
||||
super().__init__(db, Gradient.from_dict)
|
||||
if not self._items:
|
||||
self._seed_builtins()
|
||||
|
||||
@@ -70,7 +71,7 @@ class GradientStore(BaseJsonStore[Gradient]):
|
||||
logger.info(f"Seeded {len(_BUILTIN_DEFS)} built-in gradients")
|
||||
|
||||
# Aliases
|
||||
get_all_gradients = BaseJsonStore.get_all
|
||||
get_all_gradients = BaseSqliteStore.get_all
|
||||
|
||||
def get_gradient(self, gradient_id: str) -> Gradient:
|
||||
return self.get(gradient_id)
|
||||
@@ -104,7 +105,7 @@ class GradientStore(BaseJsonStore[Gradient]):
|
||||
tags=tags or [],
|
||||
)
|
||||
self._items[gid] = gradient
|
||||
self._save()
|
||||
self._save_item(gid, gradient)
|
||||
logger.info(f"Created gradient: {name} ({gid})")
|
||||
return gradient
|
||||
|
||||
@@ -129,7 +130,7 @@ class GradientStore(BaseJsonStore[Gradient]):
|
||||
if tags is not None:
|
||||
gradient.tags = tags
|
||||
gradient.updated_at = datetime.now(timezone.utc)
|
||||
self._save()
|
||||
self._save_item(gradient_id, gradient)
|
||||
logger.info(f"Updated gradient: {gradient_id}")
|
||||
return gradient
|
||||
|
||||
|
||||
Reference in New Issue
Block a user