diff options
Diffstat (limited to 'src/database/mod.rs')
| -rw-r--r-- | src/database/mod.rs | 19 |
1 files changed, 3 insertions, 16 deletions
diff --git a/src/database/mod.rs b/src/database/mod.rs index d15bb00..192416f 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs | |||
| @@ -361,24 +361,11 @@ pub async fn add_cron_job( | |||
| 361 | audio_filename: Option<&str>, | 361 | audio_filename: Option<&str>, |
| 362 | message: Option<&str>, | 362 | message: Option<&str>, |
| 363 | ) -> Result<i64> { | 363 | ) -> Result<i64> { |
| 364 | // Find the lowest unused ID to reuse freed slots | 364 | // Let SQLite allocate the id atomically; a SELECT-then-INSERT scheme |
| 365 | let existing: Vec<i64> = sqlx::query_scalar("SELECT id FROM cron_jobs ORDER BY id") | 365 | // races when two users create jobs at the same time. |
| 366 | .fetch_all(pool) | ||
| 367 | .await?; | ||
| 368 | |||
| 369 | let next_id = existing.iter().enumerate().find_map(|(i, &id)| { | ||
| 370 | let expected = (i as i64) + 1; | ||
| 371 | if id != expected { | ||
| 372 | Some(expected) | ||
| 373 | } else { | ||
| 374 | None | ||
| 375 | } | ||
| 376 | }).unwrap_or(existing.len() as i64 + 1); | ||
| 377 | |||
| 378 | let result = sqlx::query( | 366 | let result = sqlx::query( |
| 379 | "INSERT INTO cron_jobs (id, guild_id, cron_expression, type, channel_id, audio_filename, message) VALUES (?, ?, ?, ?, ?, ?, ?)", | 367 | "INSERT INTO cron_jobs (guild_id, cron_expression, type, channel_id, audio_filename, message) VALUES (?, ?, ?, ?, ?, ?)", |
| 380 | ) | 368 | ) |
| 381 | .bind(next_id) | ||
| 382 | .bind(guild_id) | 369 | .bind(guild_id) |
| 383 | .bind(cron_expression) | 370 | .bind(cron_expression) |
| 384 | .bind(r#type) | 371 | .bind(r#type) |
