Skip to content

Commit f0c3451

Browse files
committed
Added support for tasks with an external id
1 parent f0b1a11 commit f0c3451

File tree

7 files changed

+97
-10
lines changed

7 files changed

+97
-10
lines changed

dotNet/CoreHelpers.Extensions.Logging.Tasks/TaskLoggerExtension.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ public static ILoggingBuilder AddTaskLogger(this ILoggingBuilder builder)
2424

2525
public static ITaskLoggerScope? BeginNewTaskScope(this ILogger logger, string taskType, string taskSource, string taskWorker, string metaDataString, TimeSpan? cacheTimeSpan = null)
2626
=> BeginTypedTaskScope(logger, new TaskLoggerState() { TaskId = string.Empty, TaskType = taskType, TaskSource = taskSource, TaskWorker = taskWorker, IsTaskAnnounced = false, MetaData = metaDataString, CacheTimeSpan = cacheTimeSpan ?? TimeSpan.FromSeconds(30) });
27-
28-
public static ITaskLoggerScope? BeginNewTaskScopeWithExternalId(this ILogger logger, string taskId, string taskType, string taskSource, string taskWorker, string metaDataString, TimeSpan? cacheTimeSpan = null)
29-
=> BeginTypedTaskScope(logger, new TaskLoggerState() { TaskId = taskId, TaskType = taskType, TaskSource = taskSource, TaskWorker = taskWorker, IsTaskAnnounced = false, MetaData = metaDataString, CacheTimeSpan = cacheTimeSpan ?? TimeSpan.FromSeconds(30) });
30-
27+
3128
private static ITaskLoggerScope? BeginTypedTaskScope(ILogger logger, TaskLoggerState taskLoggerState)
3229
{
3330
var innerDisposable = logger.BeginScope<TaskLoggerState>(taskLoggerState);

dotNet/CoreHelpers.TaskLogging.Abstractions/ITaskLoggerFactory.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ public interface ITaskLoggerFactory
8181
/// <param name="taskWorker"></param>
8282
/// <returns></returns>
8383
Task UpdateTaskWorker(string taskId, string taskWorker);
84+
85+
/// <summary>
86+
/// Resolve an external id into the task id or returns null if not found
87+
/// </summary>
88+
/// <param name="externalTaskId"></param>
89+
/// <returns></returns>
90+
Task<string?> LookupTaskIdByExternalId(string externalTaskId);
91+
92+
93+
/// <summary>
94+
/// Registeres an external id for a given task id
95+
/// </summary>
96+
/// <param name="taskId"></param>
97+
/// <param name="externalTaskId"></param>
98+
/// <returns></returns>
99+
Task RegisterExternlIdForTask(string taskId, string externalTaskId);
84100
}
85101
}
86102

dotNet/CoreHelpers.TaskLogging.Sample/Program.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
using IHost host = builder.Build();
2828

2929
// get the worker
30-
var worker = host.Services.GetService<WorkerParallelTasks>();
30+
//var worker = host.Services.GetService<WorkerParallelTasks>();
31+
var worker = host.Services.GetService<Worker>();
3132
if (worker == null)
3233
throw new NullReferenceException();
3334

dotNet/CoreHelpers.TaskLogging.Sample/Worker.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,15 @@ public async Task Process()
4343
};
4444

4545
var taskId = await _taskLoggerFactory.AnnounceTask("announcejob", "q", "w", metaData);
46+
var externalId = Guid.NewGuid().ToString();
4647

48+
await _taskLoggerFactory.RegisterExternlIdForTask(taskId, externalId);
4749
using (_logger.BeginTaskScope(taskId))
4850
{
51+
var lookedUpTaskId = await _taskLoggerFactory.LookupTaskIdByExternalId(externalId);
52+
if (lookedUpTaskId != taskId)
53+
throw new Exception($"Task with id {lookedUpTaskId} was not found");
54+
4955
await _processors.Where(p => p is ProcessorSuccess).First().Execute();
5056
}
5157

dotNet/CoreHelpers.TaskLogging.Sample/WorkerParallelTasks.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,7 @@ private Task SpawnTask(int iTaskNumber)
4141
_logger.LogInformation($"Executing task {iTaskNumber}");
4242

4343
// create a task logger scope
44-
using var _ =
45-
iTaskNumber == 0 ?
46-
_logger.BeginNewTaskScopeWithExternalId(Guid.NewGuid().ToString(), "SpawnedTask", "WorkerParallelTasks", $"TaskWorker-{iTaskNumber}", string.Empty, TimeSpan.FromSeconds(1)) :
47-
_logger.BeginNewTaskScope("SpawnedTask", "WorkerParallelTasks", $"TaskWorker-{iTaskNumber}", TimeSpan.FromSeconds(1));
44+
using var _ = _logger.BeginNewTaskScope("SpawnedTask", "WorkerParallelTasks", $"TaskWorker-{iTaskNumber}", TimeSpan.FromSeconds(1));
4845

4946
// log something in the context of the task
5047
_logger.LogInformation($"T{iTaskNumber}: Started task {iTaskNumber}");

dotNet/CoreHelpers.TaskLogging/AzureStorageTableTaskLoggerFactory.cs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,34 @@ public async Task UpdateTaskWorker(string taskId, string taskWorker)
125125
await UpdateEntityInTable<AzureTableTaskEntity>(tableName, taskEntity);
126126
}
127127

128+
public async Task<string?> LookupTaskIdByExternalId(string externalTaskId)
129+
{
130+
// get the table name
131+
var tableName = GetExternalTaskIdLookupTable();
132+
133+
// lookup
134+
var externalIdEnties = await QueryEntitiyFromTableByPartitionKey<AzureTableTaskEntity>(tableName, externalTaskId);
135+
if (externalIdEnties.Length == 0)
136+
return null;
137+
138+
return externalIdEnties.First().RowKey;
139+
}
140+
141+
public async Task RegisterExternlIdForTask(string taskId, string externalTaskId)
142+
{
143+
// build the task entity
144+
var externalIdForTaskEntity = new AzureTableTaskEntity()
145+
{
146+
PartitionKey = externalTaskId,
147+
RowKey = taskId,
148+
};
149+
150+
// get the table name
151+
var tableName = GetExternalTaskIdLookupTable();
152+
153+
await AddEntityToTable<AzureTableTaskEntity>(tableName, externalIdForTaskEntity);
154+
}
155+
128156
public async Task<string[]> MergePendingMessagesIfNeeded(DateTimeOffset flushTime, bool force, string taskKey, string[] messages)
129157
{
130158
// check if the cache limit is exceeded
@@ -184,6 +212,9 @@ private string GetTableName(string tableName)
184212

185213
private string GetTaskTable()
186214
=> GetTableName("Tasks");
215+
216+
private string GetExternalTaskIdLookupTable()
217+
=> GetTableName("TasksExternalIdLookup");
187218

188219
private string GetRunningTaskTable()
189220
=> $"{_environmentPrefix}TasksRunning";
@@ -218,6 +249,21 @@ private async Task UpdateEntityInTable<T>(string tableName, T entity) where T :
218249
private async Task DeleteEntityByKeys(string tableName, string pKey, string rowKey)
219250
=> await ExecuteEntityToTableOperation(tableName, (TableClient tc) => tc.DeleteEntityAsync(pKey, rowKey, Azure.ETag.All));
220251

252+
private async Task<T[]> QueryEntitiyFromTableByPartitionKey<T>(string tableName, string partitionKey) where T : class, ITableEntity
253+
{
254+
var result = new List<T>();
255+
256+
await ExecuteEntityToTableOperation(tableName, async (TableClient tc) =>
257+
{
258+
var entities = tc.QueryAsync<T>(filter: $"PartitionKey eq '{partitionKey}'");
259+
260+
await foreach (var entity in entities)
261+
result.Add(entity);
262+
});
263+
264+
return result.ToArray();
265+
}
266+
221267
private async Task ExecuteEntityToTableOperation(string tableName, Func<TableClient, Task> operation)
222268
{
223269
// get the table client
@@ -232,7 +278,17 @@ private async Task ExecuteEntityToTableOperation(string tableName, Func<TableCli
232278
{
233279
if (e.ErrorCode != null && e.ErrorCode.Equals("TableNotFound"))
234280
{
235-
await tableClient.CreateAsync();
281+
try
282+
{
283+
await tableClient.CreateAsync();
284+
285+
// double check patter because of race conditions
286+
} catch(Azure.RequestFailedException e2)
287+
{
288+
if (e2.ErrorCode != null && !e2.ErrorCode.Equals("TableAlreadyExists"))
289+
throw;
290+
}
291+
236292
await operation(tableClient);
237293
}
238294
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using Azure;
3+
using Azure.Data.Tables;
4+
5+
namespace CoreHelpers.TaskLogging
6+
{
7+
public class AzureTableExternalTaskIdEntity : ITableEntity
8+
{
9+
public string PartitionKey { get; set; } = default!;
10+
public string RowKey { get; set; } = default!;
11+
public ETag ETag { get; set; } = default!;
12+
public DateTimeOffset? Timestamp { get; set; } = default!;
13+
}
14+
}

0 commit comments

Comments
 (0)