Skip to content

Commit 64b1476

Browse files
authored
Pushing DfMon Isolated for MSSQL as a separate NuGet package (#234)
* #232 * temp fix * test fix * pipeline fix * build fix * deps fix * resolving connection string and schema name * fixed host.json resolution * minor fix
1 parent cb09931 commit 64b1476

File tree

11 files changed

+716
-250
lines changed

11 files changed

+716
-250
lines changed

.github/workflows/push-to-nuget.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
jobs:
88
build:
99

10-
runs-on: ubuntu-latest
10+
runs-on: ubuntu-20.04
1111

1212
steps:
1313
- uses: actions/checkout@v4
@@ -56,20 +56,26 @@ jobs:
5656
run: dotnet publish durablefunctionsmonitor.dotnetbackend --output drop/durablefunctionsmonitor.dotnetbackend/output
5757
- name: dotnet publish durablefunctionsmonitor.dotnetisolated
5858
run: dotnet publish durablefunctionsmonitor.dotnetisolated --output drop/durablefunctionsmonitor.dotnetisolated/output
59+
- name: dotnet publish dotnetIsolated-mssql
60+
run: dotnet publish custom-backends/dotnetIsolated-mssql --output drop/dotnetIsolated-mssql/output
5961

6062
# Building nuget packages
6163

6264
- name: copy LICENSE to durablefunctionsmonitor.dotnetbackend/output
6365
run: cp LICENSE drop/durablefunctionsmonitor.dotnetbackend/output
6466
- name: copy LICENSE.txt to durablefunctionsmonitor.dotnetisolated/output
6567
run: cp durablefunctionsmonitor.dotnetisolated/LICENSE.txt drop/durablefunctionsmonitor.dotnetisolated/output
68+
- name: copy LICENSE.txt to dotnetIsolated-mssql/output
69+
run: cp durablefunctionsmonitor.dotnetisolated/LICENSE.txt drop/dotnetIsolated-mssql/output
6670

6771
- name: Install latest nuget.exe
6872
uses: nuget/setup-nuget@v1.2.0
6973
- name: package dotnetbackend into a Nuget package
7074
run: nuget pack drop/durablefunctionsmonitor.dotnetbackend/output/nuspec.nuspec -OutputDirectory drop
7175
- name: package dotnetisolated into a Nuget package
7276
run: nuget pack drop/durablefunctionsmonitor.dotnetisolated/output/nuspec.nuspec -OutputDirectory drop
77+
- name: package dotnetIsolated-mssql into a Nuget package
78+
run: nuget pack drop/dotnetIsolated-mssql/output/nuspec.nuspec -OutputDirectory drop
7379

7480
# Pushing nuget packages
7581

@@ -82,3 +88,8 @@ jobs:
8288
env:
8389
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
8490
run: nuget push drop/DurableFunctionsMonitor.DotNetBackend.*.nupkg -ApiKey $NUGET_API_KEY -src https://api.nuget.org/v3/index.json
91+
92+
- name: push drop/DurableFunctionsMonitor.DotNetIsolated.MsSql
93+
env:
94+
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
95+
run: nuget push drop/DurableFunctionsMonitor.DotNetIsolated.MsSql.*.nupkg -ApiKey $NUGET_API_KEY -src https://api.nuget.org/v3/index.json

custom-backends/dotnetIsolated-mssql/.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"azureFunctions.deploySubpath": "bin/Release/net7.0/publish",
2+
"azureFunctions.deploySubpath": "bin/Release/net8.0/publish",
33
"azureFunctions.projectLanguage": "C#",
44
"azureFunctions.projectRuntime": "~4",
55
"debug.internalConsoleOptions": "neverOpen",

custom-backends/dotnetIsolated-mssql/.vscode/tasks.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"type": "func",
6060
"dependsOn": "build (functions)",
6161
"options": {
62-
"cwd": "${workspaceFolder}/bin/Debug/net7.0"
62+
"cwd": "${workspaceFolder}/bin/Debug/net8.0"
6363
},
6464
"command": "host start",
6565
"isBackground": true,

custom-backends/dotnetIsolated-mssql/Dfm.DotNetIsolatedMsSql.csproj

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
</PropertyGroup>
99
<ItemGroup>
1010
<PackageReference Include="DurableFunctionsMonitor.DotNetIsolated" Version="6.6.0" />
11-
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.22.0" />
12-
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.3" />
1311
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer" Version="1.2.1" />
14-
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
15-
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.2" />
1612
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.0" />
1713
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\durablefunctionsmonitor.dotnetisolated.mssql\durablefunctionsmonitor.dotnetisolated.mssql.csproj" />
17+
</ItemGroup>
18+
1819
<ItemGroup>
1920
<None Update="host.json">
2021
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -23,6 +24,9 @@
2324
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2425
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
2526
</None>
27+
<None Update="nuspec.nuspec">
28+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
29+
</None>
2630
</ItemGroup>
2731
<ItemGroup>
2832
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />

custom-backends/dotnetIsolated-mssql/Program.cs

Lines changed: 3 additions & 225 deletions
Original file line numberDiff line numberDiff line change
@@ -2,244 +2,22 @@
22
// Licensed under the MIT license.
33

44
using Microsoft.Extensions.Hosting;
5-
using DurableFunctionsMonitor.DotNetIsolated;
6-
using Microsoft.Data.SqlClient;
7-
using Microsoft.DurableTask.Client;
5+
using DurableFunctionsMonitor.DotNetIsolated.MsSql;
86

97
namespace Dfm.DotNetIsolatedMsSql
108
{
119
internal class Program
1210
{
13-
private static readonly string ConnString;
14-
private static readonly string SchemaName = "dt";
15-
16-
static Program()
17-
{
18-
ConnString = Environment.GetEnvironmentVariable("DFM_SQL_CONNECTION_STRING")!;
19-
20-
// Getting custom schema name passed to us by VsCode ext
21-
string? schemaName = Environment.GetEnvironmentVariable("AzureFunctionsJobHost__extensions__durableTask__storageProvider__schemaName");
22-
if (!string.IsNullOrEmpty(schemaName))
23-
{
24-
SchemaName = schemaName;
25-
}
26-
}
27-
2811
private static void Main(string[] args)
2912
{
3013
var host = new HostBuilder()
3114
.ConfigureFunctionsWorkerDefaults((hostBuilderContext, workerAppBuilder) =>
3215
{
33-
workerAppBuilder.UseDurableFunctionsMonitor((settings, extPoints) =>
34-
{
35-
extPoints.GetInstanceHistoryRoutine = (client, connName, hubName, instanceId) => Task.FromResult(GetInstanceHistory(client, connName, hubName, instanceId));
36-
extPoints.GetParentInstanceIdRoutine = GetParentInstanceId;
37-
extPoints.GetTaskHubNamesRoutine = GetTaskHubNames;
38-
});
16+
workerAppBuilder.UseDurableFunctionsMonitorWithMsSqlDurability();
3917
})
4018
.Build();
4119

4220
host.Run();
4321
}
44-
45-
/// <summary>
46-
/// Custom routine for fetching Task Hub names
47-
/// </summary>
48-
public static async Task<IEnumerable<string>> GetTaskHubNames(string connName)
49-
{
50-
var result = new List<string>();
51-
52-
string sql =
53-
$@"SELECT DISTINCT
54-
i.TaskHub as TaskHub
55-
FROM
56-
[{SchemaName}].Instances i";
57-
58-
using (var conn = new SqlConnection(ConnString))
59-
{
60-
conn.Open();
61-
62-
using (var cmd = new SqlCommand(sql, conn))
63-
{
64-
using (var reader = cmd.ExecuteReader())
65-
{
66-
while (await reader.ReadAsync())
67-
{
68-
result.Add(reader["TaskHub"].ToString()!);
69-
}
70-
}
71-
}
72-
}
73-
74-
return result;
75-
}
76-
77-
/// <summary>
78-
/// Custom routine for fetching parent orchestration id
79-
/// </summary>
80-
public static async Task<string?> GetParentInstanceId(DurableTaskClient durableClient, string connName, string hubName, string instanceId)
81-
{
82-
string sql =
83-
$@"SELECT
84-
i.ParentInstanceID as ParentInstanceID
85-
FROM
86-
[{SchemaName}].Instances i
87-
WHERE
88-
i.InstanceID = @OrchestrationInstanceId AND i.TaskHub = @TaskHub";
89-
90-
using (var conn = new SqlConnection(ConnString))
91-
{
92-
conn.Open();
93-
94-
using (var cmd = new SqlCommand(sql, conn))
95-
{
96-
cmd.Parameters.AddWithValue("@OrchestrationInstanceId", instanceId);
97-
cmd.Parameters.AddWithValue("@TaskHub", hubName);
98-
using (var reader = cmd.ExecuteReader())
99-
{
100-
if (await reader.ReadAsync())
101-
{
102-
var parentInstanceId = reader["ParentInstanceID"];
103-
if (parentInstanceId != null)
104-
{
105-
string? parentInstanceIdString = parentInstanceId.ToString();
106-
if (!string.IsNullOrWhiteSpace(parentInstanceIdString))
107-
{
108-
return parentInstanceIdString;
109-
}
110-
}
111-
}
112-
}
113-
}
114-
}
115-
116-
return null;
117-
}
118-
119-
/// <summary>
120-
/// Custom routine for fetching orchestration history
121-
/// </summary>
122-
public static IEnumerable<HistoryEvent> GetInstanceHistory(DurableTaskClient durableClient, string connName, string hubName, string instanceId)
123-
{
124-
string sql =
125-
$@"SELECT
126-
IIF(h2.TaskID IS NULL, h.Timestamp, h2.Timestamp) as Timestamp,
127-
IIF(h2.TaskID IS NULL, h.EventType, h2.EventType) as EventType,
128-
h.TaskID as EventId,
129-
h.Name as Name,
130-
IIF(h2.TaskID IS NULL, NULL, h.Timestamp) as ScheduledTime,
131-
p1.Text as Input,
132-
p2.Text as Result,
133-
p2.Reason as Details,
134-
cih.InstanceID as SubOrchestrationId
135-
FROM
136-
[{SchemaName}].History h
137-
LEFT JOIN
138-
[{SchemaName}].History h2
139-
ON
140-
(
141-
h.EventType IN ('TaskScheduled', 'SubOrchestrationInstanceCreated')
142-
AND
143-
h2.EventType IN ('SubOrchestrationInstanceCompleted', 'SubOrchestrationInstanceFailed', 'TaskCompleted', 'TaskFailed')
144-
AND
145-
h.InstanceID = h2.InstanceID AND h.ExecutionID = h2.ExecutionID AND h.TaskHub = h2.TaskHub AND h.TaskID = h2.TaskID AND h.SequenceNumber != h2.SequenceNumber
146-
)
147-
LEFT JOIN
148-
[{SchemaName}].Payloads p1
149-
ON
150-
p1.PayloadID = h.DataPayloadID AND p1.TaskHub = h.TaskHub AND p1.InstanceID = h.InstanceID
151-
LEFT JOIN
152-
[{SchemaName}].Payloads p2
153-
ON
154-
p2.PayloadID = h2.DataPayloadID AND p2.TaskHub = h2.TaskHub AND p2.InstanceID = h2.InstanceID
155-
LEFT JOIN
156-
(
157-
select
158-
cii.ParentInstanceID,
159-
cii.InstanceID,
160-
cii.TaskHub,
161-
chh.TaskID
162-
from
163-
[{SchemaName}].Instances cii
164-
INNER JOIN
165-
[{SchemaName}].History chh
166-
ON
167-
(chh.InstanceID = cii.InstanceID AND chh.TaskHub = cii.TaskHub AND chh.EventType = 'ExecutionStarted')
168-
) cih
169-
ON
170-
(cih.ParentInstanceID = h.InstanceID AND cih.TaskHub = h.TaskHub AND cih.TaskID = h.TaskID AND h.EventType = 'SubOrchestrationInstanceCreated')
171-
WHERE
172-
h.EventType IN
173-
(
174-
'ExecutionStarted', 'ExecutionCompleted', 'ExecutionFailed', 'ExecutionTerminated', 'TaskScheduled', 'SubOrchestrationInstanceCreated',
175-
'ContinueAsNew', 'TimerCreated', 'TimerFired', 'EventRaised', 'EventSent'
176-
)
177-
AND
178-
h.InstanceID = @OrchestrationInstanceId AND h.TaskHub = @TaskHub
179-
ORDER BY
180-
h.SequenceNumber";
181-
182-
183-
using (var conn = new SqlConnection(ConnString))
184-
{
185-
conn.Open();
186-
187-
using (var cmd = new SqlCommand(sql, conn))
188-
{
189-
cmd.Parameters.AddWithValue("@OrchestrationInstanceId", instanceId);
190-
cmd.Parameters.AddWithValue("@TaskHub", hubName);
191-
using (var reader = cmd.ExecuteReader())
192-
{
193-
// Memorizing 'ExecutionStarted' event, to further correlate with 'ExecutionCompleted'
194-
DateTimeOffset? executionStartedTimestamp = null;
195-
196-
while (reader.Read())
197-
{
198-
var evt = ToHistoryEvent(reader, executionStartedTimestamp);
199-
200-
if (evt.EventType == "ExecutionStarted")
201-
{
202-
executionStartedTimestamp = evt.Timestamp;
203-
}
204-
205-
yield return evt;
206-
}
207-
}
208-
}
209-
}
210-
}
211-
212-
private static HistoryEvent ToHistoryEvent(SqlDataReader reader, DateTimeOffset? executionStartTime)
213-
{
214-
var evt = new HistoryEvent
215-
{
216-
Timestamp = ((DateTime)reader["Timestamp"]).ToUniversalTime(),
217-
EventType = reader["EventType"].ToString(),
218-
EventId = reader["EventId"] is DBNull ? null : (int?)reader["EventId"],
219-
Name = reader["Name"].ToString(),
220-
Input = reader["Input"] is DBNull ? null : reader["Input"].ToString(),
221-
Result = reader["Result"].ToString(),
222-
Details = reader["Details"].ToString(),
223-
SubOrchestrationId = reader["SubOrchestrationId"].ToString(),
224-
};
225-
226-
var rawScheduledTime = reader["ScheduledTime"];
227-
if (!(rawScheduledTime is DBNull))
228-
{
229-
evt.ScheduledTime = ((DateTime)rawScheduledTime).ToUniversalTime();
230-
}
231-
else if (evt.EventType == "ExecutionCompleted")
232-
{
233-
evt.ScheduledTime = executionStartTime?.ToUniversalTime();
234-
}
235-
236-
if (evt.ScheduledTime.HasValue)
237-
{
238-
evt.DurationInMs = (evt.Timestamp - evt.ScheduledTime.Value).TotalMilliseconds;
239-
}
240-
241-
return evt;
242-
}
24322
}
244-
}
245-
23+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0"?>
2+
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
3+
<metadata minClientVersion="2.5">
4+
<id>DurableFunctionsMonitor.DotNetIsolated.MsSql</id>
5+
<version>6.6.0-beta4</version>
6+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
7+
<description>DurableFunctionsMonitor.DotNetIsolated.MsSql</description>
8+
<authors>DurableFunctionsMonitor</authors>
9+
<repository type="git" url="https://github.com/microsoft/DurableFunctionsMonitor" />
10+
<license type="file">LICENSE.txt</license>
11+
12+
<dependencies>
13+
<dependency id="DurableFunctionsMonitor.DotNetIsolated" version="6.6.0" />
14+
<dependency id="Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer" version="1.2.1" />
15+
<dependency id="Microsoft.Data.SqlClient" version="5.2.0" />
16+
</dependencies>
17+
18+
</metadata>
19+
20+
<files>
21+
<file src="..\output\durablefunctionsmonitor.dotnetisolated.core.dll" target="lib/netcoreapp2.1" />
22+
<file src="..\output\durablefunctionsmonitor.dotnetisolated.mssql.dll" target="lib/netcoreapp2.1" />
23+
<file src="..\output\durablefunctionsmonitor.dotnetisolated.mssql.xml" target="lib/netcoreapp2.1" />
24+
<file src="..\..\durablefunctionsmonitor.dotnetisolated\durablefunctionsmonitor.dotnetisolated.targets" target="build" />
25+
<file src="..\output\*" target="/" />
26+
<file src="..\output\.azurefunctions\**" target="/.azurefunctions" />
27+
<file src="..\output\DfmStatics\**" target="/DfmStatics" />
28+
</files>
29+
</package>

0 commit comments

Comments
 (0)