public override async Task <T> GetAssetAsync <T>(Checksum checksum, CancellationToken cancellationToken) { if (_assetStorage.TryGetAsset(checksum, out T asset)) { return(asset); } using (Logger.LogBlock(FunctionId.AssetService_GetAssetAsync, Checksum.GetChecksumLogInfo, checksum, cancellationToken)) { // TODO: what happen if service doesn't come back. timeout? var value = await RequestAssetAsync(checksum, cancellationToken).ConfigureAwait(false); _assetStorage.TryAddAsset(checksum, value); return((T)value); } }
public Task SynchronizeTextAsync(DocumentId documentId, Checksum baseTextChecksum, IEnumerable <TextChange> textChanges, CancellationToken cancellationToken) { return(RunServiceAsync(async() => { using (RoslynLogger.LogBlock(FunctionId.RemoteHostService_SynchronizeTextAsync, Checksum.GetChecksumLogInfo, baseTextChecksum, cancellationToken)) { var service = SolutionService.PrimaryWorkspace.Services.GetService <ISerializerService>(); if (service == null) { return; } var text = await TryGetSourceTextAsync().ConfigureAwait(false); if (text == null) { // it won't bring in base text if it is not there already. // text needed will be pulled in when there is request return; } var newText = new WrappedText(text.WithChanges(textChanges)); var newChecksum = service.CreateChecksum(newText, cancellationToken); // save new text in the cache so that when asked, the data is most likely already there // // this cache is very short live. and new text created above is ChangedText which share // text data with original text except the changes. // so memory wise, this doesn't put too much pressure on the cache. it will not duplicates // same text multiple times. // // also, once the changes are picked up and put into Workspace, normal Workspace // caching logic will take care of the text AssetStorage.TryAddAsset(newChecksum, newText); } async Task <SourceText?> TryGetSourceTextAsync() { // check the cheap and fast one first. // see if the cache has the source text if (AssetStorage.TryGetAsset <SourceText>(baseTextChecksum, out var sourceText)) { return sourceText; } // do slower one // check whether existing solution has it var document = SolutionService.PrimaryWorkspace.CurrentSolution.GetDocument(documentId); if (document == null) { return null; } // check checksum whether it is there. // since we lazily synchronize whole solution (SynchronizePrimaryWorkspaceAsync) when things are idle, // soon or later this will get hit even if text changes got out of sync due to issues in VS side // such as file is first opened and there is no SourceText in memory yet. if (!document.State.TryGetStateChecksums(out var state) || !state.Text.Equals(baseTextChecksum)) { return null; } return await document.GetTextAsync(cancellationToken).ConfigureAwait(false); } }, cancellationToken)); }