diff options
author | dakkar <dakkar@thenautilus.net> | 2024-01-20 17:30:25 +0000 |
---|---|---|
committer | dakkar <dakkar@thenautilus.net> | 2024-01-20 17:35:21 +0000 |
commit | 491dc1aeab9b445ee28f972e19a1cbb4cb9f3af7 (patch) | |
tree | b4213dfea7e02f16e286b6b814dc196c19714cdf /lib/App/MediaControl/Model.rakumod | |
parent | quite the ScanDir supply when files are being modified (diff) | |
download | media-control-491dc1aeab9b445ee28f972e19a1cbb4cb9f3af7.tar.gz media-control-491dc1aeab9b445ee28f972e19a1cbb4cb9f3af7.tar.bz2 media-control-491dc1aeab9b445ee28f972e19a1cbb4cb9f3af7.zip |
look at fs on demand, don't watch it
ScanDir (well, fs notifications in raku) is too slow to keep up with
actual fs changes (especially when e.g. a file is being downloaded)
there's actually no need to watch fs changes, we can just sync the db
with the file system we look at each directory
Diffstat (limited to 'lib/App/MediaControl/Model.rakumod')
-rw-r--r-- | lib/App/MediaControl/Model.rakumod | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/App/MediaControl/Model.rakumod b/lib/App/MediaControl/Model.rakumod new file mode 100644 index 0000000..6d1c771 --- /dev/null +++ b/lib/App/MediaControl/Model.rakumod @@ -0,0 +1,101 @@ +use v6.d; +use App::MediaControl::FS; +use App::MediaControl::DB; + +class App::MediaControl::Model { + has App::MediaControl::FS $.fs is required; + has App::MediaControl::DB $.db is required; + + method get-children-of($id) { + my @db-children = self.db.get-children-of($id); + # [{id,path,name,is_dir,watched_time}] + + my $path; + if (@db-children) { + $path = @db-children[0]<path>; # they all have the same path + } elsif ($id.defined) { + my $entry = self.db.get-entry($id); + $path = "{$entry<path>}{$entry<name>}"; + } else { + $path = '/'; + } + + my @fs-children = self.fs.get-children-of($path); + # [{name,is_dir}] + + my ($db-idx, $fs-idx, $changed) = 0, 0, False; + + sub add-to-db() { + self.db.add-entry( + :$path, + name => @fs-children[$fs-idx]<name>, + is-dir => @fs-children[$fs-idx].<is_dir>, + ); + $changed=True; + ++$fs-idx; + } + sub remove-from-db() { + self.db.remove-entry(@db-children[$db-idx]<id>); + $changed=True; + ++$db-idx; + } + + while ($db-idx < @db-children && $fs-idx < @fs-children) { + given @db-children[$db-idx]<name> leg @fs-children[$fs-idx]<name> { + when Order::Same { + ++$db-idx; ++$fs-idx; + } + + when Order::Less { + remove-from-db(); + } + + when Order::More { + add-to-db(); + } + } + } + + while ($db-idx < @db-children) { + remove-from-db(); + } + + while ($fs-idx < @fs-children) { + add-to-db(); + } + + if $changed { + @db-children = self.db.get-children-of($id); + } + + return @db-children; + } + + method get-parents-of(Int:D() $id) { + return self.db.get-parents-of($id); + } + + method get-entry(Int:D() $id) { + return self.db.get-entry($id); + } + + method mark-entry-watched(Int:D() $id) { + return self.db.mark-entry-watched($id); + } + + method get-recently-watched-folders(Int:D() $limit=20) { + my @db-folders = self.db.get-recently-watched-folders($limit); + my $changed = False; + for @db-folders -> $f { + next if self.fs.exists("{$f<path>}{$f<name>}"); + self.db.remove-entry($f<id>); + $changed = True; + } + + if $changed { + @db-folders = self.db.get-recently-watched-folders($limit); + } + + return @db-folders; + } +} |