| 284 | } |
| 285 | |
| 286 | pub async fn get_next_task_time( |
| 287 | &self, |
| 288 | guild_id: Id<GuildMarker>, |
| 289 | ignore_ids: &[u64], |
| 290 | names: &[TaskBucketId], |
| 291 | ) -> TimerStoreResult<Option<DateTime<Utc>>> { |
| 292 | // This was a pretty fun rabbit hole to go down |
| 293 | // The problem is that postgres' multidimensional array support is trash. |
| 294 | // If i were to ask you what would the result of: |
| 295 | // ARRAY[1,2] = ANY (ARRAY[ARRAY[1,2], ARRAY[3,4]]) |
| 296 | // You would be a fool to say "true", this is actually invalid because ANY just does not care about dimensions. |
| 297 | // |
| 298 | // in fact, as i discovered, THERE IS NO WAY TO CHECK IF AN ARRAY IS CONTAINED IN A MULTI DIMENSIONAL ARRAY. |
| 299 | // |
| 300 | // So to work around this shitty flaw, just concat the nested array to a string, shitty but works for now. |
| 301 | let name_plugin_filter = names |
| 302 | .iter() |
| 303 | .map(|v| format!("{}_{}", v.plugin_id.unwrap_or(PluginId(0)).0, v.name)) |
| 304 | .collect::<Vec<_>>(); |
| 305 | |
| 306 | let res = sqlx::query!( |
| 307 | "SELECT exec_at FROM scheduled_tasks WHERE guild_id = $1 AND plugin_id || '_' || name \ |
| 308 | = ANY($2::text[]) AND (NOT id = ANY ($3::BIGINT[])) ORDER BY exec_at ASC LIMIT 1", |
| 309 | guild_id.get() as i64, |
| 310 | &name_plugin_filter, |
| 311 | &ignore_ids.iter().map(|v| *v as i64).collect::<Vec<_>>(), |
| 312 | ) |
| 313 | .fetch_optional(&self.pool) |
| 314 | .await?; |
| 315 | |
| 316 | Ok(res.map(|v| v.exec_at)) |
| 317 | } |
| 318 | |
| 319 | pub async fn get_triggered_tasks( |
| 320 | &self, |