Skip to content

Commit 3a87883

Browse files
authored
Modify rar-service design doc (#6192)
1 parent 4e4d2fd commit 3a87883

File tree

1 file changed

+28
-133
lines changed

1 file changed

+28
-133
lines changed

documentation/specs/rar-as-service.md

Lines changed: 28 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,38 @@ If the connection is successful, we can use this connection for execution of RAR
4040

4141
This step will create new process which will act as RAR node. It will also pass necessary information to the node to know what its settings are (reusable, ...). Node will be another instance of the MSBuild.exe which will have set parameter **nodeMode** to some specific value (it should be `/nodeMode:3`).
4242

43-
We will use Mutex (as in [Roslyn](https://github.com/dotnet/roslyn/blob/838874b1b817db84ce146bef690cc95a39c213a5/src/Compilers/Server/VBCSCompiler/BuildServerController.cs#L143)) to ensure we don't create two RAR nodes at once. Its name must encode whether it is the user's only RAR node, including user name, administrator privileges, and some initial settings for the node. Such a name could be: `MSBuild.RAR.ostorc.7`, where **MSBuild.RAR** is its prefix, **ostorc** is the user who called MSBuild, and **7** represents encoded settings (flag enum).
43+
We will use named-pipe exclusivity to ensure we don't create multiple RAR nodes at once. Its name must encode whether it is the user's only RAR node, including user name, administrator privileges, and some initial settings for the node. Such a name could be: `MSBuild.RAR.ostorc.7`, where **MSBuild.RAR** is its prefix, **ostorc** is the user who called MSBuild, and **7** represents encoded settings (flag enum).
44+
45+
RAR Node will adopt existing MSBuild infrastructure code, NodeProviderOutOfProcTaskHost and related, used for invoking tasks out of process.
46+
47+
This code already solved many aspect of 'Out of process task invocation':
48+
- serialization of task inputs and outputs
49+
- distributed logging
50+
- environmental variables
51+
- current directory path
52+
- current culture
53+
- cancellation
54+
- etc...
4455

4556
### Execute RAR task
4657

4758
Execution should be the same as it is now.
4859

4960
There is already some layer of separation between Task interface and actual execution method. We will leverage this, and put the decision logic if to run locally or not into the "wrapper" method and so we will not have to modify this and in server-side execution we will directly call the internal execution method.
5061

62+
#### RAR Concurrency
63+
5164
There is one big concern and that is how to handle multiple requests at once. As right now, RAR task is not prepared for multi-thread use.
5265

66+
One of the biggest challenges with RAR as service, is to make execution and caching of RAR task thread-safe, since in most cases there will be multiple clients requesting data from it at once.
67+
68+
So far, we have identified following areas that have to be addressed to allow concurrent execution of RAR tasks:
69+
70+
- thread safety (static variables, shared data structures, caching, ...)
71+
- environmental variables virtualization
72+
- current directory virtualization
73+
- current culture isolation
74+
5375
### Shutdown RAR node
5476

5577
If the user does not want the node to be reused, we have the ensure that node will be killed after the build ends. This should be done after the main MSBuild node finishes building.
@@ -70,145 +92,18 @@ __NOTE:__ The behavior described above depend on fact that the feature is opt-ou
7092

7193
## Communication
7294

73-
The communication between nodes should be done over [StreamJsonRpc](https://github.com/microsoft/vs-streamjsonrpc/). The API over which two node will transfer data has to reflect inputs and outputs of RAR task as described in [docs](https://docs.microsoft.com/visualstudio/msbuild/resolveassemblyreference-task?view=vs-2019).
74-
75-
Note that, the following snippets are probably not final version of the API and are here to give rough idea, what must be transferred.
76-
77-
### RAR Input
78-
79-
This is direct representation of all RAR inputs.
80-
81-
```csharp
82-
public sealed partial class ResolveAssemblyReferenceInput
83-
{
84-
85-
public ResolveAssemblyReferenceInput() { }
86-
87-
public string[] AllowedAssemblyExtensions { get { throw null; } set { } }
88-
89-
public string[] AllowedRelatedFileExtensions { get { throw null; } set { } }
90-
91-
public string AppConfigFile { get { throw null; } set { } }
92-
93-
public Microsoft.Build.Framework.ITaskItem[] Assemblies { get { throw null; } set { } }
94-
95-
public Microsoft.Build.Framework.ITaskItem[] AssemblyFiles { get { throw null; } set { } }
96-
97-
public bool AutoUnify { get { throw null; } set { } }
98-
99-
public string[] CandidateAssemblyFiles { get { throw null; } set { } }
100-
101-
public bool CopyLocalDependenciesWhenParentReferenceInGac { get { throw null; } set { } }
102-
103-
public bool DoNotCopyLocalIfInGac { get { throw null; } set { } }
104-
105-
public bool FindDependencies { get { throw null; } set { } }
106-
107-
public bool FindDependenciesOfExternallyResolvedReferences { get { throw null; } set { } }
108-
109-
public bool FindRelatedFiles { get { throw null; } set { } }
110-
111-
public bool FindSatellites { get { throw null; } set { } }
112-
113-
public bool FindSerializationAssemblies { get { throw null; } set { } }
114-
115-
public Microsoft.Build.Framework.ITaskItem[] FullFrameworkAssemblyTables { get { throw null; } set { } }
116-
117-
public string[] FullFrameworkFolders { get { throw null; } set { } }
118-
119-
public string[] FullTargetFrameworkSubsetNames { get { throw null; } set { } }
120-
121-
public bool IgnoreDefaultInstalledAssemblySubsetTables { get { throw null; } set { } }
122-
123-
public bool IgnoreDefaultInstalledAssemblyTables { get { throw null; } set { } }
124-
125-
public bool IgnoreTargetFrameworkAttributeVersionMismatch { get { throw null; } set { } }
126-
127-
public bool IgnoreVersionForFrameworkReferences { get { throw null; } set { } }
128-
129-
public Microsoft.Build.Framework.ITaskItem[] InstalledAssemblySubsetTables { get { throw null; } set { } }
130-
131-
public Microsoft.Build.Framework.ITaskItem[] InstalledAssemblyTables { get { throw null; } set { } }
132-
133-
public string[] LatestTargetFrameworkDirectories { get { throw null; } set { } }
134-
135-
public string ProfileName { get { throw null; } set { } }
136-
137-
public Microsoft.Build.Framework.ITaskItem[] ResolvedSDKReferences { get { throw null; } set { } }
138-
139-
public string[] SearchPaths { get { throw null; } set { } }
140-
141-
public bool Silent { get { throw null; } set { } }
142-
143-
public string StateFile { get { throw null; } set { } }
144-
145-
public bool SupportsBindingRedirectGeneration { get { throw null; } set { } }
146-
147-
public string TargetedRuntimeVersion { get { throw null; } set { } }
148-
149-
public string[] TargetFrameworkDirectories { get { throw null; } set { } }
150-
151-
public string TargetFrameworkMoniker { get { throw null; } set { } }
152-
153-
public string TargetFrameworkMonikerDisplayName { get { throw null; } set { } }
154-
155-
public string[] TargetFrameworkSubsets { get { throw null; } set { } }
156-
157-
public string TargetFrameworkVersion { get { throw null; } set { } }
158-
159-
public string TargetProcessorArchitecture { get { throw null; } set { } }
160-
161-
public bool UnresolveFrameworkAssembliesFromHigherFrameworks { get { throw null; } set { } }
162-
163-
public string WarnOrErrorOnTargetArchitectureMismatch { get { throw null; } set { } }
164-
}
165-
```
166-
167-
### RAR Output
168-
169-
Output of RAR node has to also reflect RAR task.
170-
```csharp
171-
public sealed partial class ResolveAssemblyReferenceOutput
172-
{
173-
public ResolveAssemblyReferenceOutput() { }
174-
175-
public Microsoft.Build.Framework.ITaskItem[] CopyLocalFiles { get { throw null; } }
176-
177-
public string DependsOnNETStandard { get { throw null; } }
178-
179-
public string DependsOnSystemRuntime { get { throw null; } }
180-
181-
public Microsoft.Build.Framework.ITaskItem[] FilesWritten { get { throw null; } }
182-
183-
public Microsoft.Build.Framework.ITaskItem[] RelatedFiles { get { throw null; } }
184-
185-
public Microsoft.Build.Framework.ITaskItem[] ResolvedDependencyFiles { get { throw null; } }
186-
187-
public Microsoft.Build.Framework.ITaskItem[] ResolvedFiles { get { throw null; } }
188-
189-
public Microsoft.Build.Framework.ITaskItem[] SatelliteFiles { get { throw null; } }
190-
191-
public Microsoft.Build.Framework.ITaskItem[] ScatterFiles { get { throw null; } }
192-
193-
public Microsoft.Build.Framework.ITaskItem[] SerializationAssemblyFiles { get { throw null; } }
194-
195-
public Microsoft.Build.Framework.ITaskItem[] SuggestedRedirects { get { throw null; }
196-
}
197-
```
198-
### Logging response
199-
200-
Node also has to return logged data, preferably in stream which will be transferred during the RAR task execution to the client node. This should by done by using IProgress\<T> support in StreamJsonRPC. There is also support for async enumerable, but they must be pulled and are not pushed to the client (comparison can be found [here](https://github.com/microsoft/vs-streamjsonrpc/blob/master/doc/asyncenumerable.md#comparison-with-iprogresst)).
95+
The communication between nodes should be same as current cross node communication. RAR service will allow multiple net-pipe clients, each client session handled in separate thread.
20196

202-
### Concurrency
97+
## RAR service instrumentation
20398

204-
One of the biggest challenges with RAR as service, is to make execution and caching of RAR task thread-safe, since in most cases there will be multiple clients request data from it at once.
99+
RAR will use same instrumentation infrastructure leveraged by standard MSBuild nodes. We will make sure we log all important events needed to measure, maintain and troubleshoot RAR service.
205100

206-
In the first phase of implementation the concurrency will be solved by serializing requests, but this will be replaced by optimal variant with no serializing.
101+
Instrumentation of RAR task execution will not change and will be handled by Out of process task infrastructure.
207102

208103
# Non-Goals
209104

210105
- File watchers: using them would decrease required IO operations when checking disc changes
211-
- Aggressive precomputation of results
106+
- Aggressive pre-computation of results
212107
- Improved caching of requests
213108
- Providing verbosity to RAR task:
214109
As mentioned in original [PR](https://github.com/dotnet/msbuild/pull/3914), there should be some way to determine what thing we should log (by severity), and pass back to the original node.

0 commit comments

Comments
 (0)