123 lines
3.9 KiB
Python
123 lines
3.9 KiB
Python
'''
|
|
Created on 21 août 2024
|
|
|
|
@author: denis
|
|
'''
|
|
import logging
|
|
import asyncio
|
|
from typing import Union
|
|
from abc import ABC
|
|
from reduct import Client, Bucket, BucketSettings #, QuotaType
|
|
from reduct.time import unix_timestamp_from_any, TIME_PRECISION #, unix_timestamp_to_datetime
|
|
from datetime import datetime, timedelta
|
|
from django.utils import timezone
|
|
from django.conf import settings
|
|
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class ReductStoreBase(ABC):
|
|
|
|
def __init__(self, url, api_token, name, quota_type=None, quota_size=1000_000_000):
|
|
self.bucket_name = name
|
|
self.client = Client(url, api_token=api_token)
|
|
self.quota_type = quota_type
|
|
self.quota_size = quota_size
|
|
self.bucket: Bucket = asyncio.run(self.create_bucket())
|
|
logger.info(f"==== {url} token:{api_token}")
|
|
|
|
|
|
async def create_bucket(self):
|
|
settings = BucketSettings(
|
|
quota_type=self.quota_type,
|
|
quota_size=self.quota_size,
|
|
exist_ok=True,
|
|
)
|
|
return await self.client.create_bucket(self.bucket_name, settings, exist_ok=True)
|
|
|
|
|
|
async def change_bucket(self, **settings):
|
|
new_settings = BucketSettings(**settings)
|
|
await self.bucket.set_settings(new_settings)
|
|
|
|
|
|
async def remove_bucket(self):
|
|
await self.bucket.remove()
|
|
|
|
|
|
async def write(self, entry_name, data, timestamp=None, content_type=None, labels=None):
|
|
await self.bucket.write(entry_name, data, timestamp=timestamp, content_type=content_type, labels=labels)
|
|
|
|
|
|
def query(self, entry_name, start, stop, ttl=None, when=None):
|
|
return self.bucket.query(entry_name, start=start, stop=stop, ttl=ttl, when=when)
|
|
|
|
|
|
async def remove_query(self, entry_name, start, stop, when=None):
|
|
return await self.bucket.remove_query(entry_name, start=start, stop=stop, when=when)
|
|
|
|
|
|
async def read(self, entry_name, timestamp, head=False):
|
|
async with self.bucket.read(entry_name, timestamp=timestamp, head=head) as record:
|
|
return await record.read_all()
|
|
|
|
|
|
async def record_content(self, entry_name, timestamp, head=False):
|
|
async with self.bucket.read(entry_name, timestamp=timestamp, head=head) as record:
|
|
content = await record.read_all()
|
|
return record, content
|
|
|
|
|
|
class ReductStore(ReductStoreBase):
|
|
def __init__(self, name):
|
|
super().__init__(settings.REDUCTSTORE_URL, settings.REDUCTSTORE_TOKEN, name=name)
|
|
|
|
|
|
async def old_last_dates(client_db, entry_name='uuid'):
|
|
oldest, latest = 0, 0
|
|
infos = await client_db.bucket.get_entry_list()
|
|
for info in infos:
|
|
if info.name == entry_name:
|
|
oldest, latest = info.oldest_record, info.latest_record
|
|
break
|
|
return oldest, latest
|
|
|
|
|
|
async def date_posterior_to(client_db, uuid: str, post: Union[int, str]):
|
|
last = None
|
|
oldest, latest = await old_last_dates(client_db, uuid)
|
|
if oldest and post:
|
|
dtpost = timezone.now() - timedelta(seconds=int(post))
|
|
ts = unix_timestamp_from_any(dtpost)
|
|
last = ts if ts < latest else None
|
|
return oldest, last
|
|
|
|
|
|
async def dates_filter(client_db, uuid: str, begin: Union[int, datetime, float, str],
|
|
end: Union[int, datetime, float, str] = None, duration: int = 0):
|
|
oldest, latest = await old_last_dates(client_db, uuid)
|
|
|
|
ts_from, ts_to = 0, 0
|
|
if latest:
|
|
ts_from = unix_timestamp_from_any(begin) if begin else oldest
|
|
if ts_from < oldest:
|
|
ts_from = oldest
|
|
|
|
if end is None:
|
|
if not duration:
|
|
ts_to = latest
|
|
else:
|
|
ts_to = ts_from + (duration * TIME_PRECISION)
|
|
if ts_to > latest:
|
|
ts_to = latest
|
|
else:
|
|
ts_to = unix_timestamp_from_any(end) if end else latest
|
|
if ts_to > latest:
|
|
ts_to = latest
|
|
|
|
return ts_from, ts_to if ts_from<ts_to else latest
|
|
|
|
|
|
|