0ptr/nullptr/store.py

159 lines
4.3 KiB
Python
Raw Normal View History

from nullptr.models.base import Base
from nullptr.models.waypoint import Waypoint
from nullptr.models.sector import Sector
from nullptr.models.system import System
from nullptr.models.agent import Agent
from nullptr.models.marketplace import Marketplace
from nullptr.models.system_member import SystemMember
from nullptr.models.jumpgate import Jumpgate
from nullptr.models.ship import Ship
from nullptr.models.contract import Contract
2023-06-17 18:18:14 +00:00
from nullptr.models.survey import Survey
2023-06-09 20:20:46 +00:00
from os.path import isfile, dirname, isdir
import os
2023-06-12 21:13:40 +00:00
from os.path import basename
2023-06-09 20:20:46 +00:00
import json
from .util import *
from time import time
2023-06-09 11:19:47 +00:00
class Store:
2023-06-09 20:20:46 +00:00
def __init__(self, data_dir):
self.init_models()
2023-06-09 20:20:46 +00:00
self.data_dir = data_dir
2023-06-12 21:13:40 +00:00
self.data = {m: {} for m in self.models}
self.system_members = {}
self.dirty_objects = set()
2023-06-18 05:06:32 +00:00
self.cleanup_interval = 600
self.last_cleanup = 0
def init_models(self):
self.models = all_subclasses(Base)
self.extensions = {c.ext(): c for c in self.models}
self.model_names = {c.__name__: c for c in self.models}
def dirty(self, obj):
self.dirty_objects.add(obj)
2023-06-09 20:20:46 +00:00
def path(self, obj):
return os.path.join(self.data_dir, obj.path())
2023-06-12 21:13:40 +00:00
def load_file(self, path):
2023-06-12 11:56:56 +00:00
if not isfile(path):
2023-06-12 21:13:40 +00:00
return None
fn = basename(path)
ext = fn.split('.')[-1]
symbol = fn.split('.')[0]
if ext not in self.extensions:
2023-06-12 11:56:56 +00:00
return None
with open(path) as f:
data = json.load(f)
2023-06-12 21:13:40 +00:00
typ = self.extensions[ext]
obj = self.create(typ, symbol)
obj.load(data)
obj.store = self
2023-06-12 11:56:56 +00:00
return obj
2023-06-12 21:13:40 +00:00
def load(self):
cnt = 0
start_time = time()
for fil in list_files(self.data_dir, True):
self.load_file(fil)
cnt += 1
dur = time() - start_time
print(f'loaded {cnt} objects in {dur:.2f} seconds')
2023-06-09 20:20:46 +00:00
def store(self, obj):
path = self.path(obj)
path_dir = dirname(path)
data = obj.dict()
if not isdir(path_dir):
os.makedirs(path_dir, exist_ok=True)
with open(path, 'w') as f:
json.dump(data, f, indent=2)
2023-06-12 21:13:40 +00:00
def create(self, typ, symbol):
2023-06-09 20:20:46 +00:00
obj = typ(symbol, self)
2023-06-12 21:13:40 +00:00
self.data[typ][symbol] = obj
if issubclass(typ, SystemMember):
system_str = obj.system()
if system_str not in self.system_members:
self.system_members[system_str] = set()
self.system_members[system_str].add(obj)
2023-06-09 20:20:46 +00:00
return obj
2023-06-12 21:13:40 +00:00
def get(self, typ, symbol, create=False):
if type(typ) == str and typ in self.model_names:
typ = self.model_names[typ]
symbol = symbol.upper()
2023-06-12 21:13:40 +00:00
if typ not in self.data:
return None
if symbol not in self.data[typ]:
if create:
return self.create(typ, symbol)
else:
return None
return self.data[typ][symbol]
2023-06-09 20:20:46 +00:00
def update(self, typ, data, symbol=None):
if type(typ) == str and typ in self.model_names:
typ = self.model_names[typ]
if symbol is None:
symbol = mg(data, typ.identifier)
2023-06-12 21:13:40 +00:00
obj = self.get(typ, symbol, True)
2023-06-10 18:49:50 +00:00
obj.update(data)
return obj
def update_list(self, typ, lst):
return [self.update(typ, d) for d in lst]
2023-06-10 18:49:50 +00:00
2023-06-12 21:13:40 +00:00
def all(self, typ):
if type(typ) == str and typ in self.model_names:
typ = self.model_names[typ]
2023-06-12 21:13:40 +00:00
for m in self.data[typ].values():
yield m
2023-06-10 17:39:32 +00:00
def all_members(self, system, typ=None):
if type(typ) == str and typ in self.model_names:
typ = self.model_names[typ]
if type(system) == System:
system = system.symbol
if system not in self.system_members:
return
print('typ', typ)
for m in self.system_members[system]:
if typ is None or type(m) == typ:
yield m
2023-06-18 05:06:32 +00:00
def cleanup(self):
if time() < self.last_cleanup + self.cleanup_interval:
2023-06-18 05:06:32 +00:00
return
start_time = time()
expired = list()
for t in self.data:
for o in self.all(t):
if o.is_expired():
expired.append(o)
for o in expired:
path = o.path()
if isfile(path):
os.remove(path)
del self.data[type(o)][o.symbol]
dur = time() - start_time
# print(f'cleaned {len(expired)} in {dur:.03f} seconds')
2023-06-09 20:20:46 +00:00
def flush(self):
2023-06-18 05:06:32 +00:00
self.cleanup()
it = 0
start_time = time()
for obj in self.dirty_objects:
it += 1
self.store(obj)
self.dirty_objects = set()
dur = time() - start_time
# print(f'flush done {it} items {dur:.2f}')