I have successfully migrated to ServiceStack DatabaseJobs, using a PostgreSQL DB. The process is working well for my multi-instance deployment in AWS AppRunner. However, I am now seeing Exceptions in app startup, due to a null key exception occurring in await jobs.StartAsync(stoppingToken); in my JobsHostedService.
I traced the issue back to a NULL value in the Command column in the JobSummary table. This is occurring because I am using jobs.EnqueueApi() to asynchronously invoke some API operations. When I delete the database records with the NULL values the app starts up without errors. Is there something I should be doing differently when calling jobs.EnqueueApi() to make the Command column non-NULL, or another workaround I can use?
Here is the stack trace for the Exception thrown in jobs.StartAsync():
System.ArgumentNullException: Value cannot be null. (Parameter 'key')
at System.Collections.Generic.Dictionary'2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
at System.Collections.Generic.Dictionary'2.Add(TKey key, TValue value)
at ServiceStack.OrmLite.OrmLiteReadCommandExtensions.Dictionary[K,V](IDataReader reader, IOrmLiteDialectProvider dialectProvider) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteReadCommandExtensions.cs:line 855
at ServiceStack.OrmLite.OrmLiteResultsFilterExtensions.Dictionary[K,V](IDbCommand dbCmd, ISqlExpression expression) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteResultsFilterExtensions.cs:line 297
at ServiceStack.OrmLite.OrmLiteReadApi.<>c__DisplayClass36_0'2.<Dictionary>b__0(IDbCommand dbCmd) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteReadApi.cs:line 346
at ServiceStack.OrmLite.OrmLiteExecFilter.Exec[T](IDbConnection dbConn, Func'2 filter) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteExecFilter.cs:line 70
at ServiceStack.OrmLite.OrmLiteReadExpressionsApi.Exec[T](IDbConnection dbConn, Func'2 filter) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteReadExpressionsApi.cs:line 19
at ServiceStack.OrmLite.OrmLiteReadApi.Dictionary[K,V](IDbConnection dbConn, ISqlExpression query) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack.OrmLite/src/ServiceStack.OrmLite/OrmLiteReadApi.cs:line 346
at ServiceStack.DbJobs.LoadJobQueue() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Server/DbJobs.cs:line 1002
at ServiceStack.DbJobs.StartAsync(CancellationToken stoppingToken) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack.Server/DbJobs.cs:line 971
at CTV1.JobsHostedService.ExecuteAsync(CancellationToken stoppingToken) in C:\repos\web-api\CTV1\Configure.BackgroundJobs.cs:line 75
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
I traced the error to LoadJobQueue() and this specific query:
var apiDurations = db.Dictionary<string, int>(
db.From<JobSummary>()
.Where(j => Sql.In(j.Id,
db.From<JobSummary>()
.Where(x => x.State == BackgroundJobState.Completed
&& x.DurationMs > 0
&& x.RequestType == CommandResult.Api)
.GroupBy(x => new { x.Id, x.Command, x.Worker })
.SelectDistinct(x => x.Id)))
.GroupBy(x => new { x.Command, x.Worker })
.Select(x => new {
Command = Sql.Custom($"CASE WHEN {columns.Worker} is null THEN {columns.Command} ELSE {sqlCommandWorker} END"),
DurationMs = Sql.Custom($"CASE WHEN SUM({columns.DurationMs}) > {int.MaxValue} THEN {int.MaxValue} ELSE SUM({columns.DurationMs}) END"),
}));
The NULL value in the Command column is causing the ArgumentNullException.
I have been able to work around this by adding the following lines in Configure.BackgroundJobs.cs:
using var db = jobs.OpenDb();`
await db.DeleteAsync<JobSummary>(x => x.Command == null);`
await jobs.StartAsync(stoppingToken);
Thanks for the StackTrace, the query is wrong as API should be querying Request instead of the Command column which should be resolved from this commit.
This change is available from v10.0.5+ that’s now available in the pre-release packages.
FYI, to quote a block of code in markdown, use triple back ticks, e.g:
```
Log files, Exception Stacktraces, Adhoc text blocks.
```
For marking up code with syntax highlighting, add the name of the programming language, e.g: