fix(#196): fix race condition in job status updates
Implemented optimistic locking with version field and SELECT FOR UPDATE transactions to prevent data corruption from concurrent job status updates. Changes: - Added version field to RunnerJob schema for optimistic locking - Created migration 20260202_add_runner_job_version_for_concurrency - Implemented ConcurrentUpdateException for conflict detection - Updated RunnerJobsService methods with optimistic locking: * updateStatus() - with version checking and retry logic * updateProgress() - with version checking and retry logic * cancel() - with version checking and retry logic - Updated CoordinatorIntegrationService with SELECT FOR UPDATE: * updateJobStatus() - transaction with row locking * completeJob() - transaction with row locking * failJob() - transaction with row locking * updateJobProgress() - optimistic locking - Added retry mechanism (3 attempts) with exponential backoff - Added comprehensive concurrency tests (10 tests, all passing) - Updated existing test mocks to support updateMany Test Results: - All 10 concurrency tests passing ✓ - Tests cover concurrent status updates, progress updates, completions, cancellations, retry logic, and exponential backoff This fix prevents race conditions that could cause: - Lost job results (double completion) - Lost progress updates - Invalid status transitions - Data corruption under concurrent access Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,14 +17,19 @@ export class AuthService {
|
||||
/**
|
||||
* Get BetterAuth instance
|
||||
*/
|
||||
getAuth() {
|
||||
getAuth(): Auth {
|
||||
return this.auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user by ID
|
||||
*/
|
||||
async getUserById(userId: string) {
|
||||
async getUserById(userId: string): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
authProviderId: string | null;
|
||||
} | null> {
|
||||
return this.prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
@@ -39,7 +44,12 @@ export class AuthService {
|
||||
/**
|
||||
* Get user by email
|
||||
*/
|
||||
async getUserByEmail(email: string) {
|
||||
async getUserByEmail(email: string): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
authProviderId: string | null;
|
||||
} | null> {
|
||||
return this.prisma.user.findUnique({
|
||||
where: { email },
|
||||
select: {
|
||||
|
||||
Reference in New Issue
Block a user