trackdb: Implement saving through an idle task

And register with the various subscribers that modify anything in the
trackdb.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2020-10-24 21:21:38 -04:00
parent ebb39d0600
commit a63dc5586b
2 changed files with 90 additions and 5 deletions

View File

@ -1,6 +1,9 @@
# Copyright 2020 (c) Anna Schumaker.
from lib import data
from lib import idle
from lib import publisher
import pathlib
import threading
import trackdb
import unittest
@ -14,6 +17,7 @@ class TestTrackDB(unittest.TestCase):
self.count_removed = 0
def tearDown(self):
idle.reset()
trackdb.reset()
def on_library_added(self, lib):
@ -24,8 +28,18 @@ class TestTrackDB(unittest.TestCase):
def test_trackdb_init(self):
self.assertEqual(trackdb.library_paths, [ ])
self.assertFalse(trackdb.need_save)
self.assertIsNone(trackdb.idle_id)
self.assertIsInstance(trackdb.LibraryAdded, publisher.Publisher)
self.assertIsInstance(trackdb.LibraryRemoved, publisher.Publisher)
self.assertIsInstance(trackdb.save_lock, type(threading.Lock()))
self.assertEqual(trackdb.db_file, "trackdb.pickle")
self.assertIn(trackdb.save, trackdb.LibraryAdded.subscribers)
self.assertIn(trackdb.save, trackdb.LibraryRemoved.subscribers)
self.assertIn(trackdb.save, trackdb.library.TrackAdded.subscribers)
self.assertIn(trackdb.save, trackdb.library.TrackRemoved.subscribers)
self.assertIn(trackdb.save, trackdb.track.TrackUpdated.subscribers)
def test_trackdb_add_path(self):
lib = trackdb.add_path(test_tracks)
@ -55,6 +69,26 @@ class TestTrackDB(unittest.TestCase):
self.assertEqual(trackdb.get_track(3), lib[3])
self.assertIsNone(trackdb.get_track(200))
def test_trackdb_save(self):
db_file = data.DataFile(trackdb.db_file, data.READ)
lib = trackdb.add_path(test_tracks)
lib.scan()
trackdb.save()
self.assertTrue(trackdb.need_save)
self.assertEqual(idle.Funcs, [ trackdb._do_save ])
self.assertFalse(db_file.exists())
idle.complete(delay=0.1)
self.assertIsNone(lib.thread)
self.assertEqual(idle.Funcs, [ ])
self.assertTrue(db_file.exists())
def test_trackdb_stress(self):
lib = trackdb.add_path("./trier/Test Library/")
lib.scan()
idle.complete(0.1)
def test_trackdb_reset(self):
trackdb.library.TrackAdded.register(1)
trackdb.library.TrackRemoved.register(1)
@ -62,11 +96,16 @@ class TestTrackDB(unittest.TestCase):
trackdb.LibraryAdded.register(1)
trackdb.LibraryRemoved.register(1)
trackdb.library_paths = [ 1, 2, 3 ]
trackdb.need_save = True
with data.DataFile(trackdb.db_file, data.WRITE) as f:
f.pickle([ 0, [] ])
trackdb.reset()
self.assertEqual(trackdb.library_paths, [ ])
self.assertEqual(trackdb.library.TrackAdded.subscribers, set())
self.assertEqual(trackdb.library.TrackRemoved.subscribers, set())
self.assertEqual(trackdb.track.TrackUpdated.subscribers, set())
self.assertEqual(trackdb.LibraryAdded.subscribers, set())
self.assertEqual(trackdb.LibraryRemoved.subscribers, set())
self.assertIn(trackdb.save, trackdb.library.TrackAdded.subscribers)
self.assertIn(trackdb.save, trackdb.library.TrackRemoved.subscribers)
self.assertIn(trackdb.save, trackdb.track.TrackUpdated.subscribers)
self.assertIn(trackdb.save, trackdb.LibraryAdded.subscribers)
self.assertIn(trackdb.save, trackdb.LibraryRemoved.subscribers)
self.assertFalse(trackdb.need_save)
self.assertFalse(data.DataFile(trackdb.db_file, data.READ).exists())

View File

@ -1,8 +1,16 @@
# Copyright 2020 (c) Anna Schumaker.
from lib import data
from lib import idle
from lib import publisher
from . import library
from . import track
import pathlib
import threading
db_file = "trackdb.pickle"
need_save = False
idle_id = None
save_lock = threading.Lock()
library_paths = [ ]
LibraryAdded = publisher.Publisher()
LibraryRemoved = publisher.Publisher()
@ -31,9 +39,47 @@ def remove_path(path):
library_paths.remove(lib)
LibraryRemoved.publish(lib)
def _do_save():
global need_save
global idle_id
with save_lock:
if need_save == False:
idle_id = None
return idle.REMOVE
with data.DataFile(db_file, data.WRITE) as f:
with library.IDLock:
f.pickle([ library.NextID, library_paths ])
need_save = False
return idle.CONTINUE
def save(*args):
global need_save
global idle_id
with save_lock:
if need_save == False:
need_save = True
if idle_id == None:
idle_id = idle.add(_do_save)
def __register_callbacks():
LibraryAdded.register(save)
LibraryRemoved.register(save)
library.TrackAdded.register(save)
library.TrackRemoved.register(save)
track.TrackUpdated.register(save)
__register_callbacks()
def reset():
global need_save
global idle_id
library_paths.clear()
LibraryAdded.reset()
LibraryRemoved.reset()
library.reset()
track.reset()
data.DataFile(db_file, data.READ).remove()
__register_callbacks()
need_save = False
idle_id = None