From cd7c102ca59d2c59065e5b369ebc862104ad1607 Mon Sep 17 00:00:00 2001 From: uvok Date: Mon, 20 Jan 2025 18:43:25 +0100 Subject: Add threading with fetcher loop --- hello-fusepy.py | 71 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/hello-fusepy.py b/hello-fusepy.py index fdeec00..a02bd9f 100644 --- a/hello-fusepy.py +++ b/hello-fusepy.py @@ -2,9 +2,12 @@ import argparse import enum import errno import logging +import time import requests import sys import stat +from threading import Thread, Lock +from queue import Queue from datetime import datetime as dtp from fuse import ( @@ -18,6 +21,9 @@ from fuse import ( import urllib.parse +logger = logging.getLogger(__name__) + + class APIChoice(enum.Enum): ACTIVITYPUB = "ActivityPub" MASTODON = "Mastodon" @@ -130,14 +136,13 @@ class MastodonStatusProvider(StatusProvider): class StatusFileSystem(Operations, LoggingMixIn): - def __init__(self, api: APIChoice, server: str, user: str): - self.statuses: list[Status] = [] + def __init__(self): + self._lock = Lock() + + with self._lock: + self.statuses: list[Status] = [] + self.fd = 0 - self.api = api - if api == APIChoice.MASTODON: - self.status_provider = MastodonStatusProvider(server, user) - else: - self.status_provider = ActivityPubStatusProvider(server, user) def getattr(self, path, fh=None): (uid, gid, _) = fuse_get_context() @@ -148,7 +153,9 @@ class StatusFileSystem(Operations, LoggingMixIn): "st_uid": uid, "st_gid": gid, } - found = next((s for s in self.statuses if s.id == path[1:]), None) + with self._lock: + found = next((s for s in self.statuses if s.id == path[1:]), None) + if found: published_dt = dtp.fromisoformat(found.published) pubunix = published_dt.timestamp() @@ -164,24 +171,29 @@ class StatusFileSystem(Operations, LoggingMixIn): raise FuseOSError(errno.ENOENT) def list_dir(self) -> list[str]: - return [s.id for s in self.statuses] + with self._lock: + return [s.id for s in self.statuses] def readdir(self, path, fh): dir_entries = [] if path != "/": raise FuseOSError(errno.ENOENT) dir_entries = [".", ".."] - if not self.statuses: - self.statuses = self.status_provider.load_statuses() dir_entries += self.list_dir() return dir_entries + def add_statuses(self, statuses: list[Status]): + with self._lock: + self.statuses.extend(statuses) + def open(self, path, flags): self.fd += 1 return self.fd def read(self, path, size, offset, fh): - found = next(s for s in self.statuses if s.id == path[1:]) + with self._lock: + found = next(s for s in self.statuses if s.id == path[1:]) + if found: return found.content.encode("utf8") raise FuseOSError(errno.ENOENT) @@ -215,21 +227,42 @@ def parse_arguments(): return args +# todo: make this a loop supporting paging +def status_fetcher(fs: StatusFileSystem, sp: StatusProvider): + logger.debug("Waiting to fetch statuses.") + time.sleep(5) + logger.debug("Fetch statuses.") + st = sp.load_statuses() + logger.debug("Add statuses to FS.") + fs.add_statuses(st) + logger.debug("Wait...") + time.sleep(5) + logger.debug("Done.") + def main(args): try: - FUSE( - StatusFileSystem(args.api_choice, args.server, args.username), - args.mountpoint, - nothreads=True, - foreground=True, - ) + if args.api_choice == APIChoice.MASTODON: + status_provider = MastodonStatusProvider(args.server, args.username) + else: + status_provider = ActivityPubStatusProvider(args.server, args.username) + + myfs = StatusFileSystem() + + t = Thread(target=status_fetcher, args=(myfs, status_provider)) + t.start() + + f = FUSE(myfs, args.mountpoint, nothreads=True, foreground=True) except: fuse_exit() raise + finally: + # q.join() + t.join() if __name__ == "__main__": - logging.basicConfig(level=logging.DEBUG) + logging.basicConfig(level=logging.INFO) + logger.setLevel(logging.DEBUG) args = parse_arguments() main(args) -- cgit v1.2.3