-
Notifications
You must be signed in to change notification settings - Fork 235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make the controller and repository stack async #28
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit on method naming, LGTM
{ | ||
return (Get(options)).FormattedAsCountResult<ODataPackage>(); | ||
return (await Get(options, token)).FormattedAsCountResult<ODataPackage>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
await GetAsync
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered this, but I wanted to leave the controller actions with their existing names. There is mapping logic around the $count
methods that would make changing these action names a little nasty. So I thought the cost outweighed the benefit.
{ | ||
try | ||
// Immediatelly defer work to the background thread. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Immediately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good cathc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fiixed.
|
||
return true; | ||
private Task<ServerPackage> CreateServerPackageAsync( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This private method can be synchronous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually used this method as a forcing factor to make all callers async. I picked this location since it is most likely to invoke async methods in the future 😉. However, with the Task.Yield()
in TryAddServerPackageAsync
leaves the public API the same no matter what is done in this private method. So, sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -362,61 +373,73 @@ protected virtual void Dispose(bool disposing) | |||
_serverPackageCache.PersistIfDirty(); | |||
} | |||
|
|||
private void RebuildPackageStore() | |||
private async void RebuildPackageStoreAsync(CancellationToken token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If an exception occurs in this handler, the process will terminate. It seems like we should have some recovery and/or logging here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! I didn't know fire-and-forget tasks can do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please verify the runtime behavior. I may be wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just did. You're totally right. IMO this is a bit unintuitive!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
_fileSystemWatcher.Dispose(); | ||
_fileSystemWatcher = null; | ||
|
||
_logger.Log(LogLevel.Verbose, "Destroyed FileSystemWatcher - no longer monitoring {0}.", Source); | ||
} | ||
} | ||
|
||
private void FileSystemChanged(object sender, FileSystemEventArgs e) | ||
private async void FileSystemChangedAsync(object sender, FileSystemEventArgs e) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An exception from this method would terminate the process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
{ | ||
_logger.Log(LogLevel.Error, "Error while reading packages from disk: {0} {1}", ex.Message, ex.StackTrace); | ||
_logger.Log(LogLevel.Info, "Finished reading packages from disk."); | ||
; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
return handle; | ||
} | ||
|
||
private class DisposableSemphoreSlim : IDisposable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semphore -> Semaphore
SemaphoreSlim
already implements IDisposable
, which makes this name a little nonsensical.
How about renaming to Lock
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds fine. The intend is that Dispose
releases the semaphore instead of what Semaphore.Dispose
does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
_semaphore.Release(); | ||
_lockTaken = false; | ||
} | ||
} | ||
} | ||
|
||
private class SupressedFileSystemWatcher : IDisposable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Supressed -> Suppressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
} | ||
|
||
/// <summary> | ||
/// ReadPackagesFromDisk loads all packages from disk and determines additional metadata such as the hash, IsAbsoluteLatestVersion, and IsLatestVersion. | ||
/// ReadPackagesFromDisk loads all packages from disk and determines additional metadata such as the hash, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"ReadPackagesFromDisk loads" -> "Loads"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
|
||
foreach (var packageFile in _fileSystem.GetFiles(_fileSystem.Root, "*.nupkg", false)) | ||
foreach (var packageFile in _fileSystem.GetFiles(_fileSystem.Root, "*.nupkg", false)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add named parameter for false
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
private ServerPackage CreateServerPackage( | ||
IPackage package, | ||
bool enableDelisting, | ||
CancellationToken token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The token
parameter can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I'll fix this in a subsequent PR (will have one soon for SemVer 2.0.0 which is in master but not dev).
To facilitate async IO operations at the bottom of the stack, I have changed
IServerPackageRepository
,IServerPackageStore
, andNuGetODataController
to be async.This will ease future improvements such as switching from NuGet.Core (sync APIs) to NuGet 3.x/4.x (a lot of async APIs).
/cc @dtivel @emgarten @maartenba