-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDotPythonModuleSession.cs
More file actions
108 lines (96 loc) · 3.71 KB
/
Copy pathDotPythonModuleSession.cs
File metadata and controls
108 lines (96 loc) · 3.71 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
using DotPython.Contracts;
namespace DotPython.Hosting;
/// <summary>
/// Owns typed per-session module state inside a <see cref="DotPythonHost"/>. This is not a security
/// boundary.
/// </summary>
public sealed class DotPythonModuleSession : IAsyncDisposable
{
private readonly object _gate = new();
private readonly Action<DotPythonModuleSession> _onDisposed;
private readonly DotPythonModuleProvider _provider;
private Task? _disposeTask;
internal DotPythonModuleSession(
IDotPythonModuleRuntime runtime,
Action<DotPythonModuleSession> onDisposed
)
{
_provider = new DotPythonModuleProvider(runtime);
_onDisposed = onDisposed;
}
/// <summary>Creates a typed client whose module state belongs to this session.</summary>
public TService GetModule<TService>(PythonModuleRegistration<TService> registration)
where TService : class => GetModule(registration, static _ => { });
/// <summary>Creates a configured typed client whose module state belongs to this session.</summary>
public TService GetModule<TService>(
PythonModuleRegistration<TService> registration,
Action<DotPythonModuleHostingOptions> configure
)
where TService : class
{
ArgumentNullException.ThrowIfNull(registration);
ArgumentNullException.ThrowIfNull(configure);
lock (_gate)
{
ObjectDisposedException.ThrowIf(_disposeTask is not null, this);
if (registration.StatePolicy != PythonModuleStatePolicy.PerSession)
{
throw new InvalidOperationException(
"Only per-session modules can be resolved from a DotPythonModuleSession."
);
}
DotPythonHost.ConfigureProvider(_provider, registration.Definition, configure);
return registration.CreateClient(_provider);
}
}
/// <summary>Loads and validates a per-session module before its first invocation.</summary>
public ValueTask WarmUpAsync<TService>(
PythonModuleRegistration<TService> registration,
CancellationToken cancellationToken = default
)
where TService : class => WarmUpAsync(registration, static _ => { }, cancellationToken);
/// <summary>Loads and validates a configured per-session module.</summary>
public ValueTask WarmUpAsync<TService>(
PythonModuleRegistration<TService> registration,
Action<DotPythonModuleHostingOptions> configure,
CancellationToken cancellationToken = default
)
where TService : class
{
ArgumentNullException.ThrowIfNull(registration);
ArgumentNullException.ThrowIfNull(configure);
lock (_gate)
{
ObjectDisposedException.ThrowIf(_disposeTask is not null, this);
if (registration.StatePolicy != PythonModuleStatePolicy.PerSession)
{
throw new InvalidOperationException(
"Only per-session modules can be warmed within a DotPythonModuleSession."
);
}
DotPythonHost.ConfigureProvider(_provider, registration.Definition, configure);
return _provider.WarmUpAsync(registration.Definition, cancellationToken);
}
}
/// <inheritdoc />
public ValueTask DisposeAsync()
{
lock (_gate)
{
_disposeTask ??= DisposeCoreAsync();
return new ValueTask(_disposeTask);
}
}
private async Task DisposeCoreAsync()
{
try
{
await _provider.DisposeAsync().ConfigureAwait(false);
}
finally
{
_onDisposed(this);
}
}
internal ValueTask DisposeFromHostAsync() => DisposeAsync();
}