|
6 | 6 |
|
7 | 7 | use std::{str::FromStr, time::Duration};
|
8 | 8 |
|
| 9 | +use http::StatusCode; |
9 | 10 | use redis::AsyncCommands as _;
|
| 11 | +use svix_ksuid::KsuidLike; |
10 | 12 | use svix_server::{
|
11 | 13 | cfg::Configuration,
|
12 |
| - core::types::{ApplicationId, EndpointId, MessageAttemptTriggerType, MessageId}, |
| 14 | + core::types::{ |
| 15 | + ApplicationId, BaseId, EndpointId, MessageAttemptTriggerType, MessageId, OrganizationId, |
| 16 | + }, |
13 | 17 | queue::{
|
14 | 18 | new_pair, MessageTask, QueueTask, TaskQueueConsumer, TaskQueueDelivery, TaskQueueProducer,
|
15 | 19 | },
|
16 | 20 | redis::RedisManager,
|
| 21 | + v1::endpoints::message::MessageOut, |
17 | 22 | };
|
18 | 23 | use tokio::time::timeout;
|
19 | 24 |
|
| 25 | +use crate::utils::{ |
| 26 | + common_calls::{create_test_app, create_test_endpoint, message_in}, |
| 27 | + get_default_test_config, start_svix_server_with_cfg_and_org_id_and_prefix, |
| 28 | +}; |
| 29 | + |
20 | 30 | // TODO: Don't copy this from the Redis queue test directly, place the fn somewhere both can access
|
21 | 31 | async fn get_pool(cfg: &Configuration) -> RedisManager {
|
22 | 32 | RedisManager::from_queue_backend(&cfg.queue_backend(), cfg.redis_pool_max_size).await
|
@@ -148,3 +158,90 @@ async fn test_many_queue_consumers_delayed() {
|
148 | 158 | )
|
149 | 159 | .await;
|
150 | 160 | }
|
| 161 | + |
| 162 | +#[tokio::test] |
| 163 | +#[ignore] |
| 164 | +async fn test_redis_streams_dlq() { |
| 165 | + let mut cfg = get_default_test_config(); |
| 166 | + cfg.worker_enabled = false; |
| 167 | + cfg.redis_pending_duration_secs = 1; |
| 168 | + |
| 169 | + let cfg = std::sync::Arc::new(cfg); |
| 170 | + let prefix = svix_ksuid::Ksuid::new(None, None).to_string(); |
| 171 | + |
| 172 | + let pool = get_pool(&cfg).await; |
| 173 | + let mut conn = pool.get().await.unwrap(); |
| 174 | + |
| 175 | + let _: () = conn |
| 176 | + .del(format!("{prefix}{{queue}}_svix_v3_main")) |
| 177 | + .await |
| 178 | + .unwrap(); |
| 179 | + |
| 180 | + let _: () = conn |
| 181 | + .del(format!("{prefix}{{queue}}_svix_dlq")) |
| 182 | + .await |
| 183 | + .unwrap(); |
| 184 | + |
| 185 | + let (client, _jh) = start_svix_server_with_cfg_and_org_id_and_prefix( |
| 186 | + &cfg, |
| 187 | + OrganizationId::new(None, None), |
| 188 | + prefix.clone(), |
| 189 | + ) |
| 190 | + .await; |
| 191 | + |
| 192 | + let app_id = create_test_app(&client, "v1MessageCRTestApp") |
| 193 | + .await |
| 194 | + .unwrap() |
| 195 | + .id; |
| 196 | + |
| 197 | + let _endp_id = create_test_endpoint(&client, &app_id, "http://localhost:2/bad/url/") |
| 198 | + .await |
| 199 | + .unwrap() |
| 200 | + .id; |
| 201 | + |
| 202 | + let _message_1: MessageOut = client |
| 203 | + .post( |
| 204 | + &format!("api/v1/app/{app_id}/msg/"), |
| 205 | + message_in(&app_id, serde_json::json!({"test": "value"})).unwrap(), |
| 206 | + StatusCode::ACCEPTED, |
| 207 | + ) |
| 208 | + .await |
| 209 | + .unwrap(); |
| 210 | + |
| 211 | + let (_p, mut c) = new_pair(&cfg, Some(&prefix)).await; |
| 212 | + |
| 213 | + let wait_time = std::time::Duration::from_millis(1_500); |
| 214 | + for _ in 0..3 { |
| 215 | + let res = c.receive_all(wait_time).await.unwrap(); |
| 216 | + assert!(!res.is_empty()); |
| 217 | + for j in res { |
| 218 | + j.nack().await.unwrap(); |
| 219 | + } |
| 220 | + } |
| 221 | + |
| 222 | + let res = c.receive_all(wait_time).await.unwrap(); |
| 223 | + assert!(res.is_empty()); |
| 224 | + |
| 225 | + tokio::time::sleep(wait_time).await; |
| 226 | + |
| 227 | + // Redrive |
| 228 | + client |
| 229 | + .put_without_response( |
| 230 | + "/api/v1/admin/redrive-dlq", |
| 231 | + serde_json::Value::Null, |
| 232 | + StatusCode::NO_CONTENT, |
| 233 | + ) |
| 234 | + .await |
| 235 | + .unwrap(); |
| 236 | + |
| 237 | + for _ in 0..3 { |
| 238 | + let res = c.receive_all(wait_time).await.unwrap(); |
| 239 | + assert!(!res.is_empty()); |
| 240 | + for j in res { |
| 241 | + j.nack().await.unwrap(); |
| 242 | + } |
| 243 | + } |
| 244 | + |
| 245 | + let res = c.receive_all(wait_time).await.unwrap(); |
| 246 | + assert!(res.is_empty()); |
| 247 | +} |
0 commit comments