Skip to content

Commit c8ada24

Browse files
committed
Major refactor replace MQ with BackgroundJobs
1 parent 03432fa commit c8ada24

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+632
-1245
lines changed

MyApp.ServiceInterface/AdminServices.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
using Microsoft.AspNetCore.Identity;
22
using MyApp.Data;
3+
using MyApp.ServiceInterface.AiServer;
34
using MyApp.ServiceInterface.Renderers;
45
using MyApp.ServiceModel;
56
using ServiceStack;
7+
using ServiceStack.Jobs;
68
using ServiceStack.OrmLite;
79

810
namespace MyApp.ServiceInterface;
911

10-
public class AdminServices(AppConfig appConfig, ICommandExecutor executor, UserManager<ApplicationUser> userManager,
12+
public class AdminServices(
13+
AppConfig appConfig,
14+
ICommandExecutor executor,
15+
IBackgroundJobs jobs,
16+
UserManager<ApplicationUser> userManager,
1117
QuestionsProvider questions)
1218
: Service
1319
{
@@ -50,12 +56,10 @@ public async Task<object> Any(Sync request)
5056
public async Task<object?> Any(GenerateMeta request)
5157
{
5258
var regenerateMeta = executor.Command<RegenerateMetaCommand>();
53-
await executor.ExecuteAsync(regenerateMeta, new RegenerateMeta
54-
{
59+
await executor.ExecuteAsync(regenerateMeta, new RegenerateMeta {
5560
ForPost = request.Id
5661
});
57-
58-
return regenerateMeta.Question;
62+
return regenerateMeta.Result;
5963
}
6064

6165
public async Task<object> Any(AdminResetCommonPassword request)
@@ -122,13 +126,10 @@ public async Task<object> Any(RankAnswer request)
122126

123127
if (answerCreator == null)
124128
throw HttpError.NotFound($"Answer Creator '{answer.CreatedBy}' not found");
125-
126-
MessageProducer.Publish(new AiServerTasks
127-
{
128-
CreateRankAnswerTask = new CreateRankAnswerTask {
129-
AnswerId = answer.RefId!,
130-
UserId = answerCreator,
131-
}
129+
130+
jobs.RunCommand<CreateRankAnswerTaskCommand>(new CreateRankAnswerTask {
131+
AnswerId = answer.RefId!,
132+
UserId = answerCreator,
132133
});
133134

134135
return answer;

MyApp.ServiceInterface/AiServer/CreateAnswerCommentTaskCommand.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,19 @@
55

66
namespace MyApp.ServiceInterface.AiServer;
77

8+
public class CreateAnswerCommentTask
9+
{
10+
public string? AiRef { get; set; }
11+
public string Model { get; set; }
12+
public Post Question { get; set; }
13+
public Post Answer { get; set; }
14+
public string UserId { get; set; }
15+
public string UserName { get; set; }
16+
public List<Comment> Comments { get; set; }
17+
}
18+
819
[Tag(Tags.AI)]
9-
public class CreateAnswerCommentTaskCommand(AppConfig appConfig) : IAsyncCommand<CreateAnswerCommentTask>
20+
public class CreateAnswerCommentTaskCommand(AppConfig appConfig) : AsyncCommand<CreateAnswerCommentTask>
1021
{
1122
public const string SystemPrompt =
1223
"""
@@ -18,7 +29,7 @@ I will provide you with my original question and your initial answer attempt to
1829
You should use your expertise to provide specific, concise answers to my follow up questions.
1930
""";
2031

21-
public async Task ExecuteAsync(CreateAnswerCommentTask request)
32+
protected override async Task RunAsync(CreateAnswerCommentTask request, CancellationToken token)
2233
{
2334
var question = request.Question;
2435

MyApp.ServiceInterface/AiServer/CreateRankAnswerTaskCommand.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,15 @@
44

55
namespace MyApp.ServiceInterface.AiServer;
66

7+
public class CreateRankAnswerTask
8+
{
9+
public string AnswerId { get; set; }
10+
public string UserId { get; set; }
11+
}
12+
713
[Tag(Tags.AI)]
8-
public class CreateRankAnswerTaskCommand(AppConfig appConfig, QuestionsProvider questions) : IAsyncCommand<CreateRankAnswerTask>
14+
public class CreateRankAnswerTaskCommand(AppConfig appConfig, QuestionsProvider questions)
15+
: IAsyncCommand<CreateRankAnswerTask>
916
{
1017
//https://github.com/f/awesome-chatgpt-prompts?tab=readme-ov-file#act-as-a-tech-reviewer
1118
public const string SystemPrompt =

MyApp.ServiceInterface/AiServerServices.cs

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
using Microsoft.Extensions.Logging;
55
using MyApp.Data;
66
using MyApp.ServiceInterface.AiServer;
7+
using MyApp.ServiceInterface.App;
78
using MyApp.ServiceModel;
89
using ServiceStack;
10+
using ServiceStack.Jobs;
911
using ServiceStack.OrmLite;
1012

1113
namespace MyApp.ServiceInterface;
@@ -15,7 +17,8 @@ public class AiServerServices(ILogger<AiServerServices> log,
1517
QuestionsProvider questions,
1618
RendererCache rendererCache,
1719
WorkerAnswerNotifier answerNotifier,
18-
ICommandExecutor executor) : Service
20+
ICommandExecutor executor,
21+
IBackgroundJobs jobs) : Service
1922
{
2023
public async Task<object> Any(CreateAnswersForModels request)
2124
{
@@ -94,29 +97,23 @@ public async Task Any(CreateAnswerCallback request)
9497

9598
await questions.SaveAnswerAsync(answer);
9699

97-
MessageProducer.Publish(new DbWrites
100+
jobs.RunCommand<SaveGradeResultCommand>(new StatTotals
98101
{
99-
SaveStartingUpVotes = new()
100-
{
101-
Id = answer.RefId!,
102-
PostId = request.PostId,
103-
StartingUpVotes = 0,
104-
CreatedBy = modelUser.UserName,
105-
LastUpdated = DateTime.UtcNow,
106-
}
102+
Id = answer.RefId!,
103+
PostId = request.PostId,
104+
StartingUpVotes = 0,
105+
CreatedBy = modelUser.UserName,
106+
LastUpdated = DateTime.UtcNow,
107107
});
108108

109-
await Db.NotifyQuestionAuthorIfRequiredAsync(MessageProducer, answer);
110-
111-
MessageProducer.Publish(new AiServerTasks
112-
{
113-
CreateRankAnswerTask = new CreateRankAnswerTask {
114-
AnswerId = answer.RefId!,
115-
UserId = request.UserId,
116-
}
109+
await Db.NotifyQuestionAuthorIfRequiredAsync(jobs, answer);
110+
111+
jobs.RunCommand<CreateRankAnswerTaskCommand>(new CreateRankAnswerTask {
112+
AnswerId = answer.RefId!,
113+
UserId = request.UserId,
117114
});
118-
119-
MessageProducer.Publish(new SearchTasks {
115+
116+
jobs.RunCommand<SearchTasksCommand>(new SearchTasks {
120117
AddAnswerToIndex = answer.RefId
121118
});
122119
}
@@ -173,11 +170,8 @@ public async Task Any(RankAnswerCallback request)
173170
meta.StatTotals.Add(statTotals);
174171

175172
await questions.SaveMetaAsync(request.PostId, meta);
176-
177-
MessageProducer.Publish(new DbWrites
178-
{
179-
SaveStartingUpVotes = statTotals
180-
});
173+
174+
jobs.RunCommand<SaveGradeResultCommand>(statTotals);
181175
}
182176
catch (Exception e)
183177
{
@@ -223,14 +217,10 @@ public async Task Any(AnswerCommentCallback request)
223217
};
224218
comments.Add(newComment);
225219

226-
MessageProducer.Publish(new DbWrites
227-
{
228-
NewComment = new()
229-
{
230-
RefId = request.AnswerId,
231-
Comment = newComment,
232-
LastUpdated = DateTime.UtcNow,
233-
},
220+
jobs.RunCommand<NewCommentCommand>(new NewComment {
221+
RefId = request.AnswerId,
222+
Comment = newComment,
223+
LastUpdated = DateTime.UtcNow,
234224
});
235225

236226
await questions.SaveMetaAsync(postId, meta);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using MyApp.Data;
2+
using MyApp.ServiceModel;
3+
using ServiceStack;
4+
using ServiceStack.IO;
5+
using ServiceStack.OrmLite;
6+
7+
namespace MyApp.ServiceInterface;
8+
9+
[Worker(Databases.Analytics)]
10+
public class AnalyticsTasksCommand(R2VirtualFiles r2, QuestionsProvider questions) : AsyncCommand<AnalyticsTasks>
11+
{
12+
protected override async Task RunAsync(AnalyticsTasks request, CancellationToken token)
13+
{
14+
if (request.CreatePostStat == null && request.CreateSearchStat == null && request.DeletePost == null)
15+
return;
16+
17+
using var analyticsDb = HostContext.AppHost.GetDbConnection(Databases.Analytics);
18+
19+
if (request.CreatePostStat != null)// && !Stats.IsAdminOrModerator(request.RecordPostView.UserName))
20+
{
21+
await analyticsDb.InsertAsync(request.CreatePostStat, token: token);
22+
}
23+
24+
if (request.CreateSearchStat != null)// && !Stats.IsAdminOrModerator(request.RecordSearchView.UserName))
25+
{
26+
await analyticsDb.InsertAsync(request.CreateSearchStat, token: token);
27+
}
28+
29+
if (request.DeletePost != null)
30+
{
31+
await analyticsDb.DeleteAsync<PostStat>(x => x.PostId == request.DeletePost, token: token);
32+
}
33+
}
34+
}

MyApp.ServiceInterface/App/AnswerAddedToPostCommand.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
namespace MyApp.ServiceInterface.App;
88

99
[Tag(Tags.Answers)]
10-
public class AnswerAddedToPostCommand(IDbConnection db) : IAsyncCommand<AnswerAddedToPost>
10+
[Worker(Databases.App)]
11+
public class AnswerAddedToPostCommand(IDbConnection db) : AsyncCommand<AnswerAddedToPost>
1112
{
12-
public async Task ExecuteAsync(AnswerAddedToPost request)
13+
protected override async Task RunAsync(AnswerAddedToPost request, CancellationToken token)
1314
{
1415
await db.UpdateAddAsync(() => new Post {
1516
AnswerCount = 1,
16-
}, x => x.Id == request.Id);
17+
}, x => x.Id == request.Id, token:token);
1718
}
1819
}

MyApp.ServiceInterface/App/CreateAnswerCommand.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace MyApp.ServiceInterface.App;
88

99
[Tag(Tags.Answers)]
10+
[Worker(Databases.App)]
1011
public class CreateAnswerCommand(AppConfig appConfig, IDbConnection db) : IAsyncCommand<Post>
1112
{
1213
public async Task ExecuteAsync(Post answer)

MyApp.ServiceInterface/App/CreateFlagCommand.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
namespace MyApp.ServiceInterface.App;
77

88
[Tag(Tags.Database)]
9-
public class CreateFlagCommand(IDbConnection db) : IAsyncCommand<Flag>
9+
[Worker(Databases.App)]
10+
public class CreateFlagCommand(IDbConnection db) : AsyncCommand<Flag>
1011
{
11-
public async Task ExecuteAsync(Flag request)
12+
protected override async Task RunAsync(Flag request, CancellationToken token)
1213
{
13-
await db.InsertAsync(request);
14+
await db.InsertAsync(request, token: token);
1415
}
1516
}

MyApp.ServiceInterface/App/CreateNotificationCommand.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
namespace MyApp.ServiceInterface.App;
88

99
[Tag(Tags.Notifications)]
10-
public class CreateNotificationCommand(AppConfig appConfig, IDbConnection db) : IAsyncCommand<Notification>
10+
[Worker(Databases.App)]
11+
public class CreateNotificationCommand(AppConfig appConfig, IDbConnection db) : AsyncCommand<Notification>
1112
{
12-
public async Task ExecuteAsync(Notification request)
13+
protected override async Task RunAsync(Notification request, CancellationToken token)
1314
{
14-
await db.InsertAsync(request);
15+
await db.InsertAsync(request, token: token);
1516
appConfig.IncrUnreadNotificationsFor(request.UserName);
1617
}
17-
}
18+
}

MyApp.ServiceInterface/App/CreatePostCommand.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@
77

88
namespace MyApp.ServiceInterface.App;
99

10+
[Worker(Databases.App)]
1011
[Tag(Tags.Questions)]
11-
public class CreatePostCommand(ILogger<CreatePostCommand> log, AppConfig appConfig, IDbConnection db) : IAsyncCommand<Post>
12+
public class CreatePostCommand(ILogger<CreatePostCommand> log, AppConfig appConfig, IDbConnection db) : AsyncCommand<Post>
1213
{
13-
public async Task ExecuteAsync(Post post)
14+
protected override async Task RunAsync(Post post, CancellationToken token)
1415
{
1516
var body = post.Body;
1617
post.Body = null;
1718

1819
if (post.Id > 0)
1920
{
20-
await db.InsertAsync(post);
21+
await db.InsertAsync(post, token: token);
2122
}
2223
else
2324
{
24-
post.Id = (int)await db.InsertAsync(post, selectIdentity: true);
25+
post.Id = (int)await db.InsertAsync(post, selectIdentity: true, token: token);
2526
}
2627

2728
var createdBy = post.CreatedBy;
@@ -40,7 +41,7 @@ await db.InsertAsync(new StatTotals
4041
DownVotes = 0,
4142
StartingUpVotes = 0,
4243
CreatedBy = post.CreatedBy,
43-
});
44+
}, token: token);
4445
}
4546
catch (Exception e)
4647
{
@@ -50,7 +51,7 @@ await db.InsertAsync(new StatTotals
5051
{
5152
PostId = post.Id,
5253
CreatedBy = post.CreatedBy,
53-
}, x => x.Id == $"{post.Id}");
54+
}, x => x.Id == $"{post.Id}", token: token);
5455
}
5556

5657
if (!string.IsNullOrEmpty(body))
@@ -61,7 +62,7 @@ await db.InsertAsync(new StatTotals
6162
if (userNameMentions.Count > 0)
6263
{
6364
var existingUsers = await db.SelectAsync(db.From<ApplicationUser>()
64-
.Where(x => userNameMentions.Contains(x.UserName!)));
65+
.Where(x => userNameMentions.Contains(x.UserName!)), token: token);
6566

6667
foreach (var existingUser in existingUsers)
6768
{
@@ -80,7 +81,7 @@ await db.InsertAsync(new Notification
8081
CreatedDate = post.CreationDate,
8182
Summary = cleanBody.GenerateNotificationSummary(startPos),
8283
RefUserName = createdBy,
83-
});
84+
}, token: token);
8485
appConfig.IncrUnreadNotificationsFor(existingUser.UserName!);
8586
}
8687
}
@@ -97,7 +98,7 @@ await db.InsertAsync(new Achievement
9798
PostId = post.Id,
9899
Score = 1,
99100
CreatedDate = DateTime.UtcNow,
100-
});
101+
}, token: token);
101102
appConfig.IncrUnreadAchievementsFor(post.CreatedBy!);
102103

103104
// Setup auto-watch for new questions (Sending Emails for new Answers)
@@ -108,7 +109,7 @@ await db.InsertAsync(new WatchPost
108109
CreatedDate = post.CreationDate,
109110
// Email new answers 1hr after asking question
110111
AfterDate = DateTime.UtcNow.Add(TimeSpan.FromHours(1)),
111-
});
112+
}, token: token);
112113
}
113114
}
114115
}

0 commit comments

Comments
 (0)