mirror of
https://github.com/koel/koel
synced 2024-11-10 22:54:16 +00:00
Refactor and fix the file watcher
This commit is contained in:
parent
34c4a8e369
commit
03d6c06aef
3 changed files with 51 additions and 52 deletions
|
@ -23,6 +23,8 @@ class FSWatchRecord
|
|||
*/
|
||||
protected $eventFlags;
|
||||
|
||||
protected $watchedEvents = ['Created', 'Removed', 'Renamed', 'Updated'];
|
||||
|
||||
/**
|
||||
* Construct an FSWatchRecord object for a record string.
|
||||
*
|
||||
|
@ -36,6 +38,23 @@ class FSWatchRecord
|
|||
$this->path = implode(' ', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the event is valid to Koel.
|
||||
* We only watch Created, Removed, Renamed, and Updated events.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isValidEvent()
|
||||
{
|
||||
foreach ($this->watchedEvents as $e) {
|
||||
if (in_array($e, $this->eventFlags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the file/directory is deleted from the system.
|
||||
* We can't rely on fswatch, since the event is OS-dependent.
|
||||
|
@ -49,16 +68,6 @@ class FSWatchRecord
|
|||
return !file_exists($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the object is renamed.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRenamed()
|
||||
{
|
||||
return in_array('Renamed', $this->eventFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the changed object is a file.
|
||||
*
|
||||
|
@ -66,7 +75,7 @@ class FSWatchRecord
|
|||
*/
|
||||
public function isFile()
|
||||
{
|
||||
return in_array('IsFile', $this->eventFlags);
|
||||
return is_file($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,7 +85,7 @@ class FSWatchRecord
|
|||
*/
|
||||
public function isDir()
|
||||
{
|
||||
return in_array('IsDir', $this->eventFlags);
|
||||
return is_dir($this->path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -151,54 +151,41 @@ class Media
|
|||
$record = new FSWatchRecord($record);
|
||||
}
|
||||
|
||||
if (!$record->isValidEvent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$path = $record->getPath();
|
||||
|
||||
if ($record->isFile()) {
|
||||
// If the file has been deleted...
|
||||
if ($record->isDeleted()) {
|
||||
// ...and it has a record in our database, remove it.
|
||||
if ($song = Song::byPath($path)) {
|
||||
$song->delete();
|
||||
|
||||
Log::info("Deleted $path");
|
||||
|
||||
event(new LibraryChanged());
|
||||
}
|
||||
}
|
||||
// Otherwise, it's a new or changed file. Try to sync it in.
|
||||
// File format etc. will be handled by the syncFile method.
|
||||
else {
|
||||
Log::info("Syncing file $path");
|
||||
Log::info($this->syncFile($path) instanceof Song ? "Synchronized $path" : "Invalid file $path");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($record->isDir()) {
|
||||
if ($record->isDeleted()) {
|
||||
// A whole directory is removed.
|
||||
// We remove all songs in it.
|
||||
Song::inDirectory($path)->delete();
|
||||
|
||||
Log::info("Deleted all song(s) under $path");
|
||||
|
||||
event(new LibraryChanged());
|
||||
} elseif ($record->isRenamed()) {
|
||||
foreach ($this->gatherFiles($path) as $file) {
|
||||
$this->syncFile($file);
|
||||
}
|
||||
|
||||
Log::info("Synced all song(s) under $path");
|
||||
if ($record->isDeleted()) {
|
||||
// Since the item has been deleted, we can't tell if it was a file or a directory.
|
||||
// So here we're assuming it to be a file first, and directory second.
|
||||
if ($song = Song::byPath($path)) {
|
||||
$song->delete();
|
||||
Log::info("Deleted $path");
|
||||
} else {
|
||||
// "New directory" fswatch event actually comes with individual "new file" events,
|
||||
// which should already be handled by our logic above.
|
||||
Song::inDirectory($path)->delete();
|
||||
Log::info("Deleted all song(s) under $path");
|
||||
}
|
||||
|
||||
event(new LibraryChanged());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// The changed item is a symlink maybe. But we're not doing anything with it.
|
||||
// Now if the added/modified item is a file, we simply sync it into the database.
|
||||
if ($record->isFile()) {
|
||||
Log::info("Syncing file $path");
|
||||
Log::info($this->syncFile($path) instanceof Song ? "Synchronized $path" : "Invalid file $path");
|
||||
}
|
||||
// But if it's a whole directory, we traverse through it and sync all children.
|
||||
else {
|
||||
foreach ($this->gatherFiles($path) as $file) {
|
||||
$this->syncFile($file);
|
||||
}
|
||||
|
||||
Log::info("Synced all song(s) under $path");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -73,6 +73,7 @@ class MediaTest extends TestCase
|
|||
'isDeleted' => false,
|
||||
'getPath' => $path,
|
||||
'isFile' => true,
|
||||
'isValidEvent' => true,
|
||||
], ["$path IsFile"]);
|
||||
|
||||
(new Media())->syncFSWatchRecord($record);
|
||||
|
@ -91,6 +92,7 @@ class MediaTest extends TestCase
|
|||
'isDeleted' => true,
|
||||
'getPath' => $song->path,
|
||||
'isFile' => true,
|
||||
'isValidEvent' => true,
|
||||
], ["{$song->path} IsFile"]);
|
||||
|
||||
(new Media())->syncFSWatchRecord($record);
|
||||
|
@ -111,6 +113,7 @@ class MediaTest extends TestCase
|
|||
'getPath' => $path,
|
||||
'isFile' => false,
|
||||
'isDir' => true,
|
||||
'isValidEvent' => true,
|
||||
], ["$path IsDir"]);
|
||||
|
||||
$media->syncFSWatchRecord($record);
|
||||
|
|
Loading…
Reference in a new issue