file_manager: add metadata scan endpoint

Support manual scan requests for systems where inotify
does not function correctlly (network shares).  This endpoint
may also be used to force a rescan of files that have already
had an initial scan.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2023-02-21 12:10:46 -05:00
parent 9178b3833c
commit dce3b9eaf5
No known key found for this signature in database
GPG Key ID: 5A1EB336DFB4C71B
1 changed files with 33 additions and 5 deletions

View File

@ -108,6 +108,8 @@ class FileManager:
"/server/files/list", ['GET'], self._handle_filelist_request)
self.server.register_endpoint(
"/server/files/metadata", ['GET'], self._handle_metadata_request)
self.server.register_endpoint(
"/server/files/metascan", ['POST'], self._handle_metascan_request)
self.server.register_endpoint(
"/server/files/thumbnails", ['GET'], self._handle_list_thumbs)
self.server.register_endpoint(
@ -380,6 +382,31 @@ class FileManager:
metadata['filename'] = requested_file
return metadata
async def _handle_metascan_request(
self, web_request: WebRequest
) -> Dict[str, Any]:
async with self.sync_lock:
requested_file: str = web_request.get_str('filename')
gcpath = pathlib.Path(self.file_paths["gcodes"]).joinpath(requested_file)
if not gcpath.is_file():
raise self.server.error(f"File '{requested_file}' does not exist", 404)
if gcpath.suffix not in VALID_GCODE_EXTS:
raise self.server.error(f"File {gcpath} is not a valid gcode file")
# remove metadata and force a rescan
ret = self.gcode_metadata.remove_file_metadata(requested_file)
if ret is not None:
await ret
path_info = self.get_path_info(gcpath, "gcodes")
evt = self.gcode_metadata.parse_metadata(requested_file, path_info)
await evt.wait()
metadata: Optional[Dict[str, Any]]
metadata = self.gcode_metadata.get(requested_file, None)
if metadata is None:
raise self.server.error(
f"Failed to parse metadata for file '{requested_file}'", 500)
metadata['filename'] = requested_file
return metadata
async def _handle_list_roots(
self, web_request: WebRequest
) -> List[Dict[str, Any]]:
@ -2250,7 +2277,7 @@ class MetadataStorage:
return False
return True
def remove_directory_metadata(self, dir_name: str) -> None:
def remove_directory_metadata(self, dir_name: str) -> Optional[Awaitable]:
if dir_name[-1] != "/":
dir_name += "/"
del_items: Dict[str, Any] = {}
@ -2264,15 +2291,16 @@ class MetadataStorage:
self.mddb.delete_batch(list(del_items.keys()))
eventloop = self.server.get_event_loop()
# Remove thumbs in a nother thread
eventloop.run_in_thread(self._remove_thumbs, del_items)
return eventloop.run_in_thread(self._remove_thumbs, del_items)
return None
def remove_file_metadata(self, fname: str) -> None:
def remove_file_metadata(self, fname: str) -> Optional[Awaitable]:
md: Optional[Dict[str, Any]] = self.metadata.pop(fname, None)
if md is None:
return
return None
self.mddb.pop(fname, None)
eventloop = self.server.get_event_loop()
eventloop.run_in_thread(self._remove_thumbs, {fname: md})
return eventloop.run_in_thread(self._remove_thumbs, {fname: md})
def _remove_thumbs(self, records: Dict[str, Dict[str, Any]]) -> None:
for fname, metadata in records.items():