Refactor and fix the file watcher

This commit is contained in:
An Phan 2016-02-02 18:04:10 +08:00
parent 34c4a8e369
commit 03d6c06aef
3 changed files with 51 additions and 52 deletions

View file

@ -23,6 +23,8 @@ class FSWatchRecord
*/ */
protected $eventFlags; protected $eventFlags;
protected $watchedEvents = ['Created', 'Removed', 'Renamed', 'Updated'];
/** /**
* Construct an FSWatchRecord object for a record string. * Construct an FSWatchRecord object for a record string.
* *
@ -36,6 +38,23 @@ class FSWatchRecord
$this->path = implode(' ', $parts); $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. * Determine if the file/directory is deleted from the system.
* We can't rely on fswatch, since the event is OS-dependent. * We can't rely on fswatch, since the event is OS-dependent.
@ -49,16 +68,6 @@ class FSWatchRecord
return !file_exists($this->path); 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. * Determine if the changed object is a file.
* *
@ -66,7 +75,7 @@ class FSWatchRecord
*/ */
public function isFile() public function isFile()
{ {
return in_array('IsFile', $this->eventFlags); return is_file($this->path);
} }
/** /**
@ -76,7 +85,7 @@ class FSWatchRecord
*/ */
public function isDir() public function isDir()
{ {
return in_array('IsDir', $this->eventFlags); return is_dir($this->path);
} }
/** /**

View file

@ -151,54 +151,41 @@ class Media
$record = new FSWatchRecord($record); $record = new FSWatchRecord($record);
} }
if (!$record->isValidEvent()) {
return;
}
$path = $record->getPath(); $path = $record->getPath();
if ($record->isFile()) { if ($record->isDeleted()) {
// If the file has been deleted... // Since the item has been deleted, we can't tell if it was a file or a directory.
if ($record->isDeleted()) { // So here we're assuming it to be a file first, and directory second.
// ...and it has a record in our database, remove it. if ($song = Song::byPath($path)) {
if ($song = Song::byPath($path)) { $song->delete();
$song->delete(); Log::info("Deleted $path");
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");
} else { } else {
// "New directory" fswatch event actually comes with individual "new file" events, Song::inDirectory($path)->delete();
// which should already be handled by our logic above. Log::info("Deleted all song(s) under $path");
} }
event(new LibraryChanged());
return; 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");
}
} }
/** /**

View file

@ -73,6 +73,7 @@ class MediaTest extends TestCase
'isDeleted' => false, 'isDeleted' => false,
'getPath' => $path, 'getPath' => $path,
'isFile' => true, 'isFile' => true,
'isValidEvent' => true,
], ["$path IsFile"]); ], ["$path IsFile"]);
(new Media())->syncFSWatchRecord($record); (new Media())->syncFSWatchRecord($record);
@ -91,6 +92,7 @@ class MediaTest extends TestCase
'isDeleted' => true, 'isDeleted' => true,
'getPath' => $song->path, 'getPath' => $song->path,
'isFile' => true, 'isFile' => true,
'isValidEvent' => true,
], ["{$song->path} IsFile"]); ], ["{$song->path} IsFile"]);
(new Media())->syncFSWatchRecord($record); (new Media())->syncFSWatchRecord($record);
@ -111,6 +113,7 @@ class MediaTest extends TestCase
'getPath' => $path, 'getPath' => $path,
'isFile' => false, 'isFile' => false,
'isDir' => true, 'isDir' => true,
'isValidEvent' => true,
], ["$path IsDir"]); ], ["$path IsDir"]);
$media->syncFSWatchRecord($record); $media->syncFSWatchRecord($record);