mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 06:00:33 +02:00
Store: publish a search's completion and hand over its queue atomically
A query arriving between the queue handover and the completion event could be queued with nobody to start it, leaving the source 'loading' forever. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
5ac109c381
commit
4fd8bb79af
2 files changed
+24
-2
No files matched your search
@@ -95,6 +95,28 @@ class SearchTests(SettingsTest):
|
||||
finally:
|
||||
release.set()
|
||||
|
||||
def test_query_arriving_as_a_search_finishes_is_not_stranded(self):
|
||||
mod = fake()
|
||||
source = mod.sources()[0]
|
||||
arrived = []
|
||||
|
||||
class Event(threading.Event):
|
||||
def set(self):
|
||||
if not arrived: # a request lands just as the first search completes
|
||||
arrived.append(None)
|
||||
t = threading.Thread(target=lambda: arrived.append(search._launch(mod, source, 'second', 50)))
|
||||
t.start()
|
||||
t.join(.3) # blocks on search._lock if completion is published atomically
|
||||
super().set()
|
||||
with patch.object(search, 'threading', types.SimpleNamespace(Event=Event, Thread=threading.Thread)):
|
||||
search._launch(mod, source, 'first', 50)
|
||||
for _ in range(200):
|
||||
if len(arrived) == 2:
|
||||
break
|
||||
time.sleep(.01)
|
||||
self.assertTrue(arrived[1]['event'].wait(2))
|
||||
self.assertEqual(arrived[1]['query'], ('second', 50))
|
||||
|
||||
def test_set_enabled_does_not_hold_search_lock_in_source(self):
|
||||
free = []
|
||||
def set_enabled(source_id, enabled):
|
||||
|
||||
@@ -249,11 +249,11 @@ def _start(key, task):
|
||||
task['error'] = str(e)
|
||||
task['limited'] = isinstance(e, SourceLimited)
|
||||
finally:
|
||||
with _lock:
|
||||
with _lock: # completion and queue handover are one step for _launch
|
||||
queued = _pending.pop(key, None)
|
||||
if queued:
|
||||
_running[key] = queued
|
||||
task['event'].set()
|
||||
task['event'].set()
|
||||
if queued:
|
||||
_start(key, queued)
|
||||
threading.Thread(target=run, daemon=True).start()
|
||||
|
||||
Reference in new issue
Block a user