Exemple #1
0
        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));
        }