| 659 | } |
| 660 | |
| 661 | pub async fn get_schedulable_queue_items(limit: usize) -> Result<Vec<MulticastGroupQueueItem>> { |
| 662 | let mut c = get_async_db_conn().await?; |
| 663 | c.transaction::<Vec<MulticastGroupQueueItem>, Error, _>(async |c| { |
| 664 | let conf = config::get(); |
| 665 | diesel::sql_query(if cfg!(feature = "sqlite") { |
| 666 | r#" |
| 667 | update |
| 668 | multicast_group_queue_item |
| 669 | set |
| 670 | scheduler_run_after = ?3 |
| 671 | where |
| 672 | id in ( |
| 673 | select |
| 674 | id |
| 675 | from |
| 676 | multicast_group_queue_item |
| 677 | where |
| 678 | scheduler_run_after <= ?2 |
| 679 | order by |
| 680 | created_at |
| 681 | limit ?1 |
| 682 | ) |
| 683 | returning * |
| 684 | "# |
| 685 | } else { |
| 686 | r#" |
| 687 | update |
| 688 | multicast_group_queue_item |
| 689 | set |
| 690 | scheduler_run_after = $3 |
| 691 | where |
| 692 | id in ( |
| 693 | select |
| 694 | qi.id |
| 695 | from |
| 696 | multicast_group_queue_item qi |
| 697 | inner join gateway g |
| 698 | on g.gateway_id = qi.gateway_id |
| 699 | where |
| 700 | qi.scheduler_run_after <= $2 |
| 701 | -- check that the gateway is online, except when the item already has expired |
| 702 | and ($2 - make_interval(secs => g.stats_interval_secs * 2) <= g.last_seen_at or expires_at <= $2) |
| 703 | order by |
| 704 | qi.created_at |
| 705 | limit $1 |
| 706 | for update skip locked |
| 707 | ) |
| 708 | returning * |
| 709 | "# |
| 710 | }) |
| 711 | .bind::<diesel::sql_types::Integer, _>(limit as i32) |
| 712 | .bind::<fields::sql_types::Timestamptz, _>(Utc::now()) |
| 713 | .bind::<fields::sql_types::Timestamptz, _>( |
| 714 | Utc::now() + Duration::from_std(conf.network.scheduler.scheduler_lock_duration).unwrap(), |
| 715 | ) |
| 716 | .load(c) |
| 717 | .await |
| 718 | .map_err(|e| Error::from_diesel(e, "".into())) |