-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorkerHostOptions.cs
More file actions
184 lines (164 loc) · 6.9 KB
/
Copy pathWorkerHostOptions.cs
File metadata and controls
184 lines (164 loc) · 6.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
using System.Globalization;
using DotPython.Protocol;
using DotPython.Runtime.Native;
namespace DotPython.Worker.Host;
internal sealed record WorkerHostOptions(
WorkerIdentity Identity,
WorkerProtocolLimits Limits,
IReadOnlyList<string> PackageRoots,
IReadOnlyList<StableAbiModuleCatalogEntry> StableAbiModules,
bool TestFaultInjection,
WorkerProtocolVersion ProtocolVersion
)
{
internal static WorkerHostOptions Parse(IReadOnlyList<string> arguments)
{
ArgumentNullException.ThrowIfNull(arguments);
var values = new Dictionary<string, List<string>>(StringComparer.Ordinal);
var testFaultInjection = false;
for (var index = 0; index < arguments.Count; index++)
{
var name = arguments[index];
if (name == "--test-fault-injection")
{
testFaultInjection = true;
continue;
}
if (!name.StartsWith("--", StringComparison.Ordinal) || index + 1 >= arguments.Count)
{
throw new ArgumentException($"Invalid worker argument '{name}'.");
}
if (!values.TryGetValue(name, out var entries))
{
entries = [];
values.Add(name, entries);
}
entries.Add(arguments[++index]);
}
var packageRoots = values.TryGetValue("--package-root", out var roots) ? roots : [];
foreach (var root in packageRoots)
{
if (!Path.IsPathFullyQualified(root) || !Directory.Exists(root))
{
throw new ArgumentException($"Worker package root '{root}' is invalid.");
}
if ((File.GetAttributes(root) & FileAttributes.ReparsePoint) != 0)
{
throw new ArgumentException($"Worker package root '{root}' cannot be a link.");
}
}
var features = new List<string> { "managed-execution", "cancellation", "sessions" };
if (testFaultInjection)
{
features.Add("test-fault-injection");
}
IReadOnlyList<StableAbiModuleCatalogEntry> stableAbiModules = [];
var hasNativeModule = values.ContainsKey("--abi3-module");
if (hasNativeModule)
{
var bridgePath = Required(values, "--abi3-bridge");
var bridgeSha256 = Required(values, "--abi3-bridge-sha256");
var modulePaths = RequiredMany(values, "--abi3-module");
var manifestPaths = RequiredMany(values, "--abi3-manifest");
var moduleHashes = RequiredMany(values, "--abi3-module-sha256");
var manifestHashes = RequiredMany(values, "--abi3-manifest-sha256");
if (
modulePaths.Count > 64
|| manifestPaths.Count != modulePaths.Count
|| moduleHashes.Count != modulePaths.Count
|| manifestHashes.Count != modulePaths.Count
)
{
throw new ArgumentException(
"The Stable-ABI module catalog is misaligned or exceeds its 64-module bound."
);
}
var entries = new List<StableAbiModuleCatalogEntry>(modulePaths.Count);
for (var index = 0; index < modulePaths.Count; index++)
{
var configuration = new StableAbiModuleConfiguration(
bridgePath,
modulePaths[index],
manifestPaths[index],
bridgeSha256,
moduleHashes[index],
manifestHashes[index]
);
var manifest = StableAbiSymbolManifest.Load(configuration.ManifestPath);
entries.Add(new StableAbiModuleCatalogEntry(configuration, manifest));
}
stableAbiModules = StableAbiModuleCatalog.ValidateAndFreeze(entries);
features.AddRange(
stableAbiModules.Select(entry => entry.Manifest.CapabilityId).Distinct()
);
}
else if (values.Keys.Any(key => key.StartsWith("--abi3-", StringComparison.Ordinal)))
{
throw new ArgumentException("The Stable-ABI module configuration is incomplete.");
}
var protocolMajor = values.TryGetValue("--protocol-major", out var majorValues)
? ParsePositive(majorValues.Single(), "--protocol-major")
: WorkerProtocolVersion.Current.Major;
return new WorkerHostOptions(
new WorkerIdentity(
Required(values, "--provider-id"),
Required(values, "--provider-version"),
Required(values, "--runtime-id"),
Required(values, "--runtime-version"),
Required(values, "--architecture"),
Required(values, "--environment-hash"),
Guid.Parse(Required(values, "--worker-id")),
ParsePositiveLong(Required(values, "--generation"), "--generation"),
features
),
new WorkerProtocolLimits(
ParsePositive(Required(values, "--max-message-bytes"), "--max-message-bytes"),
ParsePositive(Required(values, "--max-output-bytes"), "--max-output-bytes"),
ParsePositive(Required(values, "--max-concurrency"), "--max-concurrency"),
ParsePositive(Required(values, "--max-sessions"), "--max-sessions")
),
packageRoots,
stableAbiModules,
testFaultInjection,
new WorkerProtocolVersion(protocolMajor, WorkerProtocolVersion.Current.Minor)
);
}
private static List<string> RequiredMany(Dictionary<string, List<string>> values, string name)
{
if (!values.TryGetValue(name, out var entries) || entries.Count == 0)
{
throw new ArgumentException($"Worker argument '{name}' must occur at least once.");
}
return entries;
}
private static string Required(Dictionary<string, List<string>> values, string name)
{
if (!values.TryGetValue(name, out var entries) || entries.Count != 1)
{
throw new ArgumentException($"Worker argument '{name}' must occur exactly once.");
}
return entries[0];
}
private static int ParsePositive(string value, string name)
{
if (
!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var result)
|| result <= 0
)
{
throw new ArgumentException($"Worker argument '{name}' must be a positive integer.");
}
return result;
}
private static long ParsePositiveLong(string value, string name)
{
if (
!long.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out var result)
|| result <= 0
)
{
throw new ArgumentException($"Worker argument '{name}' must be a positive integer.");
}
return result;
}
}