@@ -229,6 +229,9 @@ pub fn sql_tests() -> Vec<(&'static str, TestFn)> {
229229 t( "cache_prefix_keys" , cache_prefix_keys) ,
230230 t( "queue_full_workflow" , queue_full_workflow) ,
231231 t( "queue_ack_then_result" , queue_ack_then_result) ,
232+ t( "queue_orphaned_timeout" , queue_orphaned_timeout) ,
233+ t( "queue_heartbeat" , queue_heartbeat) ,
234+ t( "queue_merge_extra" , queue_merge_extra) ,
232235 t(
233236 "queue_multiple_result_blocking" ,
234237 queue_multiple_result_blocking,
@@ -6667,6 +6670,152 @@ async fn queue_ack_then_result(service: Box<dyn SqlClient>) {
66676670 assert_eq ! ( result. get_rows( ) . len( ) , 0 ) ;
66686671}
66696672
6673+ async fn queue_orphaned_timeout ( service : Box < dyn SqlClient > ) {
6674+ service
6675+ . exec_query ( r#"QUEUE ADD PRIORITY 1 "STANDALONE#queue:1" "payload1";"# )
6676+ . await
6677+ . unwrap ( ) ;
6678+
6679+ service
6680+ . exec_query ( r#"QUEUE ADD PRIORITY 1 "STANDALONE#queue:2" "payload2";"# )
6681+ . await
6682+ . unwrap ( ) ;
6683+
6684+ let res = service
6685+ . exec_query ( r#"QUEUE TO_CANCEL 1000 1000 "STANDALONE#queue";"# )
6686+ . await
6687+ . unwrap ( ) ;
6688+ assert_eq ! ( res. len( ) , 0 ) ;
6689+
6690+ // only active jobs can be orphaned
6691+ // RETRIEVE updates heartbeat
6692+ {
6693+ service
6694+ . exec_query ( r#"QUEUE RETRIEVE CONCURRENCY 2 "STANDALONE#queue:1""# )
6695+ . await
6696+ . unwrap ( ) ;
6697+
6698+ service
6699+ . exec_query ( r#"QUEUE RETRIEVE CONCURRENCY 2 "STANDALONE#queue:2""# )
6700+ . await
6701+ . unwrap ( ) ;
6702+ }
6703+
6704+ tokio:: time:: sleep ( Duration :: from_millis ( 1000 ) ) . await ;
6705+
6706+ service
6707+ . exec_query ( r#"QUEUE HEARTBEAT "STANDALONE#queue:2";"# )
6708+ . await
6709+ . unwrap ( ) ;
6710+
6711+ let res = service
6712+ . exec_query ( r#"QUEUE TO_CANCEL 1000 1000 "STANDALONE#queue""# )
6713+ . await
6714+ . unwrap ( ) ;
6715+ assert_eq ! (
6716+ res. get_columns( ) ,
6717+ & vec![ Column :: new( "id" . to_string( ) , ColumnType :: String , 0 ) , ]
6718+ ) ;
6719+ assert_eq ! (
6720+ res. get_rows( ) ,
6721+ & vec![ Row :: new( vec![ TableValue :: String ( "1" . to_string( ) ) , ] ) , ]
6722+ ) ;
6723+
6724+ // awaiting for expiring heart beat for queue:2
6725+ tokio:: time:: sleep ( Duration :: from_millis ( 1000 ) ) . await ;
6726+
6727+ let res = service
6728+ . exec_query ( r#"QUEUE TO_CANCEL 1000 1000 "STANDALONE#queue""# )
6729+ . await
6730+ . unwrap ( ) ;
6731+ assert_eq ! ( res. len( ) , 2 ) ;
6732+ }
6733+
6734+ async fn queue_heartbeat ( service : Box < dyn SqlClient > ) {
6735+ service
6736+ . exec_query ( r#"QUEUE ADD PRIORITY 1 "STANDALONE#queue:1" "payload1";"# )
6737+ . await
6738+ . unwrap ( ) ;
6739+
6740+ let res = service
6741+ . exec_query ( r#"SELECT heartbeat FROM system.queue WHERE prefix = 'STANDALONE#queue'"# )
6742+ . await
6743+ . unwrap ( ) ;
6744+ assert_eq ! ( res. get_rows( ) , & vec![ Row :: new( vec![ TableValue :: Null , ] ) , ] ) ;
6745+
6746+ service
6747+ . exec_query ( r#"QUEUE HEARTBEAT "STANDALONE#queue:1";"# )
6748+ . await
6749+ . unwrap ( ) ;
6750+
6751+ let res = service
6752+ . exec_query ( r#"SELECT heartbeat FROM system.queue WHERE prefix = 'STANDALONE#queue'"# )
6753+ . await
6754+ . unwrap ( ) ;
6755+
6756+ let row = res. get_rows ( ) . first ( ) . unwrap ( ) ;
6757+ match row. values ( ) . first ( ) . unwrap ( ) {
6758+ TableValue :: Timestamp ( _) => { }
6759+ other => panic ! ( "heartbeat must be a timestamp type, actual: {:?}" , other) ,
6760+ }
6761+ }
6762+
6763+ async fn queue_merge_extra ( service : Box < dyn SqlClient > ) {
6764+ service
6765+ . exec_query ( r#"QUEUE ADD PRIORITY 1 "STANDALONE#queue:1" "payload1";"# )
6766+ . await
6767+ . unwrap ( ) ;
6768+
6769+ // extra must be empty after creation
6770+ {
6771+ let res = service
6772+ . exec_query ( r#"QUEUE GET "STANDALONE#queue:1";"# )
6773+ . await
6774+ . unwrap ( ) ;
6775+ assert_eq ! (
6776+ res. get_columns( ) ,
6777+ & vec![
6778+ Column :: new( "payload" . to_string( ) , ColumnType :: String , 0 ) ,
6779+ Column :: new( "extra" . to_string( ) , ColumnType :: String , 1 ) ,
6780+ ]
6781+ ) ;
6782+ assert_eq ! (
6783+ res. get_rows( ) ,
6784+ & vec![ Row :: new( vec![
6785+ TableValue :: String ( "payload1" . to_string( ) ) ,
6786+ TableValue :: Null
6787+ ] ) , ]
6788+ ) ;
6789+ }
6790+
6791+ service
6792+ . exec_query ( r#"QUEUE MERGE_EXTRA "STANDALONE#queue:1" '{"first": true}';"# )
6793+ . await
6794+ . unwrap ( ) ;
6795+
6796+ // extra should contains first field
6797+ {
6798+ let res = service
6799+ . exec_query ( r#"QUEUE GET "STANDALONE#queue:1";"# )
6800+ . await
6801+ . unwrap ( ) ;
6802+ assert_eq ! (
6803+ res. get_columns( ) ,
6804+ & vec![
6805+ Column :: new( "payload" . to_string( ) , ColumnType :: String , 0 ) ,
6806+ Column :: new( "extra" . to_string( ) , ColumnType :: String , 1 ) ,
6807+ ]
6808+ ) ;
6809+ assert_eq ! (
6810+ res. get_rows( ) ,
6811+ & vec![ Row :: new( vec![
6812+ TableValue :: String ( "payload1" . to_string( ) ) ,
6813+ TableValue :: String ( "{\" first\" : true}" . to_string( ) )
6814+ ] ) , ]
6815+ ) ;
6816+ }
6817+ }
6818+
66706819async fn queue_multiple_result_blocking ( service : Box < dyn SqlClient > ) {
66716820 service
66726821 . exec_query ( r#"QUEUE ADD PRIORITY 1 "STANDALONE#queue:12345" "payload1";"# )
0 commit comments