@scrypted/server 0.7.7 → 0.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @scrypted/server might be problematic. Click here for more details.

@@ -331,7 +331,7 @@ class MediaManagerBase {
331
331
  node[candidateId] = inputWeight + outputWeight;
332
332
  }
333
333
  catch (e) {
334
- console.warn(converter.name, 'skipping converter due to error', e);
334
+ console.warn(candidate.name, 'skipping converter due to error', e);
335
335
  }
336
336
  }
337
337
  // source matches
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrypted/server",
3
- "version": "0.7.7",
3
+ "version": "0.7.9",
4
4
  "description": "",
5
5
  "dependencies": {
6
6
  "@mapbox/node-pre-gyp": "^1.0.10",
@@ -8,6 +8,7 @@ import platform
8
8
  import shutil
9
9
  import subprocess
10
10
  import threading
11
+ import concurrent.futures
11
12
  import time
12
13
  import traceback
13
14
  import zipfile
@@ -35,6 +36,24 @@ class SystemDeviceState(TypedDict):
35
36
  value: any
36
37
 
37
38
 
39
+ class StreamPipeReader:
40
+ def __init__(self, conn: multiprocessing.connection.Connection) -> None:
41
+ self.conn = conn
42
+ self.executor = concurrent.futures.ThreadPoolExecutor()
43
+
44
+ def readBlocking(self, n):
45
+ b = bytes(0)
46
+ while len(b) < n:
47
+ self.conn.poll()
48
+ add = os.read(self.conn.fileno(), n - len(b))
49
+ if not len(add):
50
+ raise Exception('unable to read requested bytes')
51
+ b += add
52
+ return b
53
+
54
+ async def read(self, n):
55
+ return await asyncio.get_event_loop().run_in_executor(self.executor, lambda: self.readBlocking(n))
56
+
38
57
  class SystemManager(scrypted_python.scrypted_sdk.types.SystemManager):
39
58
  def __init__(self, api: Any, systemState: Mapping[str, Mapping[str, SystemDeviceState]]) -> None:
40
59
  super().__init__()
@@ -466,15 +485,18 @@ class PluginRemote:
466
485
  schedule_exit_check()
467
486
 
468
487
  async def getFork():
469
- fd = os.dup(parent_conn.fileno())
470
- forkPeer, readLoop = await rpc_reader.prepare_peer_readloop(self.loop, fd, fd)
488
+ reader = StreamPipeReader(parent_conn)
489
+ forkPeer, readLoop = await rpc_reader.prepare_peer_readloop(self.loop, reader = reader, writeFd = parent_conn.fileno())
471
490
  forkPeer.peerName = 'thread'
472
491
  async def forkReadLoop():
473
492
  try:
474
493
  await readLoop()
475
494
  except:
495
+ # traceback.print_exc()
476
496
  print('fork read loop exited')
477
- pass
497
+ finally:
498
+ parent_conn.close()
499
+ reader.executor.shutdown()
478
500
  asyncio.run_coroutine_threadsafe(forkReadLoop(), loop=self.loop)
479
501
  getRemote = await forkPeer.getParam('getRemote')
480
502
  remote: PluginRemote = await getRemote(self.api, self.pluginId, self.hostInfo)
@@ -563,13 +585,15 @@ class PluginRemote:
563
585
  async def getServicePort(self, name):
564
586
  pass
565
587
 
566
- async def plugin_async_main(loop: AbstractEventLoop, readFd: int, writeFd: int):
567
- peer, readLoop = await rpc_reader.prepare_peer_readloop(loop, readFd, writeFd)
588
+ async def plugin_async_main(loop: AbstractEventLoop, readFd: int = None, writeFd: int = None, reader: asyncio.StreamReader = None, writer: asyncio.StreamWriter = None):
589
+ peer, readLoop = await rpc_reader.prepare_peer_readloop(loop, readFd=readFd, writeFd=writeFd, reader=reader, writer=writer)
568
590
  peer.params['print'] = print
569
591
  peer.params['getRemote'] = lambda api, pluginId, hostInfo: PluginRemote(peer, api, pluginId, hostInfo, loop)
570
592
 
571
593
  async def get_update_stats():
572
594
  update_stats = await peer.getParam('updateStats')
595
+ if not update_stats:
596
+ return
573
597
 
574
598
  def stats_runner():
575
599
  ptime = round(time.process_time() * 1000000)
@@ -601,10 +625,14 @@ async def plugin_async_main(loop: AbstractEventLoop, readFd: int, writeFd: int):
601
625
 
602
626
  asyncio.run_coroutine_threadsafe(get_update_stats(), loop)
603
627
 
604
- await readLoop()
605
-
628
+ try:
629
+ await readLoop()
630
+ finally:
631
+ if reader and hasattr(reader, 'executor'):
632
+ r: StreamPipeReader = reader
633
+ r.executor.shutdown()
606
634
 
607
- def main(readFd: int, writeFd: int):
635
+ def main(readFd: int = None, writeFd: int = None, reader: asyncio.StreamReader = None, writer: asyncio.StreamWriter = None):
608
636
  loop = asyncio.new_event_loop()
609
637
 
610
638
  def gc_runner():
@@ -612,10 +640,10 @@ def main(readFd: int, writeFd: int):
612
640
  loop.call_later(10, gc_runner)
613
641
  gc_runner()
614
642
 
615
- loop.run_until_complete(plugin_async_main(loop, readFd, writeFd))
643
+ loop.run_until_complete(plugin_async_main(loop, readFd=readFd, writeFd=writeFd, reader=reader, writer=writer))
616
644
  loop.close()
617
645
 
618
- def plugin_main(readFd: int, writeFd: int):
646
+ def plugin_main(readFd: int = None, writeFd: int = None, reader: asyncio.StreamReader = None, writer: asyncio.StreamWriter = None):
619
647
  try:
620
648
  import gi
621
649
  gi.require_version('Gst', '1.0')
@@ -624,17 +652,18 @@ def plugin_main(readFd: int, writeFd: int):
624
652
 
625
653
  loop = GLib.MainLoop()
626
654
 
627
- worker = threading.Thread(target=main, args=(readFd, writeFd), name="asyncio-main")
655
+ worker = threading.Thread(target=main, args=(readFd, writeFd, reader, writer), name="asyncio-main")
628
656
  worker.start()
629
657
 
630
658
  loop.run()
631
659
  except:
632
- main(readFd, writeFd)
660
+ main(readFd=readFd, writeFd=writeFd, reader=reader, writer=writer)
633
661
 
634
662
 
635
663
  def plugin_fork(conn: multiprocessing.connection.Connection):
636
664
  fd = os.dup(conn.fileno())
637
- plugin_main(fd, fd)
665
+ reader = StreamPipeReader(conn)
666
+ plugin_main(reader=reader, writeFd=fd)
638
667
 
639
668
  if __name__ == "__main__":
640
669
  plugin_main(3, 4)
@@ -385,7 +385,7 @@ export abstract class MediaManagerBase implements MediaManager {
385
385
  node[candidateId] = inputWeight + outputWeight;
386
386
  }
387
387
  catch (e) {
388
- console.warn(converter.name, 'skipping converter due to error', e)
388
+ console.warn(candidate.name, 'skipping converter due to error', e)
389
389
  }
390
390
  }
391
391