@@ -4,21 +4,12 @@ use crate::{
44 RsmqError , RsmqResult ,
55} ;
66use core:: convert:: TryFrom ;
7- use lazy_static:: lazy_static;
87use radix_fmt:: radix_36;
98use rand:: seq:: IteratorRandom ;
10- use redis:: { aio:: ConnectionLike , pipe, Script } ;
9+ use redis:: { aio:: ConnectionLike , pipe} ;
1110use std:: convert:: TryInto ;
1211use std:: time:: Duration ;
1312
14- lazy_static ! {
15- static ref CHANGE_MESSAGE_VISIVILITY : Script =
16- Script :: new( include_str!( "./redis-scripts/changeMessageVisibility.lua" ) ) ;
17- static ref POP_MESSAGE : Script = Script :: new( include_str!( "./redis-scripts/popMessage.lua" ) ) ;
18- static ref RECEIVE_MESSAGE : Script =
19- Script :: new( include_str!( "./redis-scripts/receiveMessage.lua" ) ) ;
20- }
21-
2213const JS_COMPAT_MAX_TIME_MILLIS : u64 = 9_999_999_000 ;
2314
2415#[ cfg( feature = "break-js-comp" ) ]
@@ -40,6 +31,75 @@ impl<T: ConnectionLike> std::fmt::Debug for RsmqFunctions<T> {
4031 }
4132}
4233
34+ #[ derive( Debug , Clone ) ]
35+ pub struct CachedScript {
36+ change_message_visibility_sha1 : String ,
37+ receive_message_sha1 : String ,
38+ }
39+
40+ impl CachedScript {
41+ async fn init < T : ConnectionLike > ( conn : & mut T ) -> RsmqResult < Self > {
42+ let change_message_visibility_sha1: String = redis:: cmd ( "SCRIPT" )
43+ . arg ( "LOAD" )
44+ . arg ( include_str ! ( "./redis-scripts/changeMessageVisibility.lua" ) )
45+ . query_async ( conn)
46+ . await ?;
47+ let receive_message_sha1: String = redis:: cmd ( "SCRIPT" )
48+ . arg ( "LOAD" )
49+ . arg ( include_str ! ( "./redis-scripts/receiveMessage.lua" ) )
50+ . query_async ( conn)
51+ . await ?;
52+ Ok ( Self {
53+ change_message_visibility_sha1,
54+ receive_message_sha1,
55+ } )
56+ }
57+
58+ async fn invoke_change_message_visibility < R , T : ConnectionLike > (
59+ & self ,
60+ conn : & mut T ,
61+ key1 : String ,
62+ key2 : String ,
63+ key3 : String ,
64+ ) -> RsmqResult < R >
65+ where
66+ R : redis:: FromRedisValue ,
67+ {
68+ redis:: cmd ( "EVALSHA" )
69+ . arg ( & self . change_message_visibility_sha1 )
70+ . arg ( 3 )
71+ . arg ( key1)
72+ . arg ( key2)
73+ . arg ( key3)
74+ . query_async ( conn)
75+ . await
76+ . map_err ( Into :: into)
77+ }
78+
79+ async fn invoke_receive_message < R , T : ConnectionLike > (
80+ & self ,
81+ conn : & mut T ,
82+ key1 : String ,
83+ key2 : String ,
84+ key3 : String ,
85+ should_delete : String ,
86+ ) -> RsmqResult < R >
87+ where
88+ R : redis:: FromRedisValue ,
89+ {
90+ redis:: cmd ( "EVALSHA" )
91+ . arg ( & self . receive_message_sha1 )
92+ . arg ( 3 )
93+ . arg ( key1)
94+ . arg ( key2)
95+ . arg ( key3)
96+ . arg ( should_delete)
97+ . query_async ( conn)
98+ . await
99+ . map_err ( Into :: into)
100+ }
101+ }
102+
43103impl < T : ConnectionLike > RsmqFunctions < T > {
44104 /// Change the hidden time of a already sent message.
45105 pub async fn change_message_visibility (
@@ -48,23 +108,30 @@ impl<T: ConnectionLike> RsmqFunctions<T> {
48108 qname : & str ,
49109 message_id : & str ,
50110 hidden : Duration ,
111+ cached_script : & CachedScript ,
51112 ) -> RsmqResult < ( ) > {
52113 let hidden = get_redis_duration ( Some ( hidden) , & Duration :: from_secs ( 30 ) ) ;
53114
54115 let queue = self . get_queue ( conn, qname, false ) . await ?;
55116
56117 number_in_range ( hidden, 0 , JS_COMPAT_MAX_TIME_MILLIS ) ?;
57118
58- CHANGE_MESSAGE_VISIVILITY
59- . key ( format ! ( "{}:{}" , self . ns, qname) )
60- . key ( message_id)
61- . key ( queue. ts + hidden)
62- . invoke_async :: < _ , bool > ( conn)
119+ cached_script
120+ . invoke_change_message_visibility :: < _ , T > (
121+ conn,
122+ format ! ( "{}:{}" , self . ns, qname) ,
123+ message_id. to_string ( ) ,
124+ ( queue. ts + hidden) . to_string ( ) ,
125+ )
63126 . await ?;
64127
65128 Ok ( ( ) )
66129 }
67130
131+ pub async fn load_scripts ( & self , conn : & mut T ) -> RsmqResult < CachedScript > {
132+ CachedScript :: init ( conn) . await
133+ }
134+
68135 /// Creates a new queue. Attributes can be later modified with "set_queue_attributes" method
69136 ///
70137 /// hidden: Time the messages will be hidden when they are received with the "receive_message" method.
@@ -266,13 +333,18 @@ impl<T: ConnectionLike> RsmqFunctions<T> {
266333 & self ,
267334 conn : & mut T ,
268335 qname : & str ,
336+ cached_script : & CachedScript ,
269337 ) -> RsmqResult < Option < RsmqMessage < E > > > {
270338 let queue = self . get_queue ( conn, qname, false ) . await ?;
271339
272- let result: ( bool , String , Vec < u8 > , u64 , u64 ) = POP_MESSAGE
273- . key ( format ! ( "{}:{}" , self . ns, qname) )
274- . key ( queue. ts )
275- . invoke_async ( conn)
340+ let result: ( bool , String , Vec < u8 > , u64 , u64 ) = cached_script
341+ . invoke_receive_message (
342+ conn,
343+ format ! ( "{}:{}" , self . ns, qname) ,
344+ queue. ts . to_string ( ) ,
345+ queue. ts . to_string ( ) ,
346+ "true" . to_string ( ) ,
347+ )
276348 . await ?;
277349
278350 if !result. 0 {
@@ -298,17 +370,21 @@ impl<T: ConnectionLike> RsmqFunctions<T> {
298370 conn : & mut T ,
299371 qname : & str ,
300372 hidden : Option < Duration > ,
373+ cached_script : & CachedScript ,
301374 ) -> RsmqResult < Option < RsmqMessage < E > > > {
302375 let queue = self . get_queue ( conn, qname, false ) . await ?;
303376
304377 let hidden = get_redis_duration ( hidden, & queue. vt ) ;
305378 number_in_range ( hidden, 0 , JS_COMPAT_MAX_TIME_MILLIS ) ?;
306379
307- let result: ( bool , String , Vec < u8 > , u64 , u64 ) = RECEIVE_MESSAGE
308- . key ( format ! ( "{}:{}" , self . ns, qname) )
309- . key ( queue. ts )
310- . key ( queue. ts + hidden)
311- . invoke_async ( conn)
380+ let result: ( bool , String , Vec < u8 > , u64 , u64 ) = cached_script
381+ . invoke_receive_message (
382+ conn,
383+ format ! ( "{}:{}" , self . ns, qname) ,
384+ queue. ts . to_string ( ) ,
385+ ( queue. ts + hidden) . to_string ( ) ,
386+ "false" . to_string ( ) ,
387+ )
312388 . await ?;
313389
314390 if !result. 0 {
@@ -474,7 +550,7 @@ impl<T: ConnectionLike> RsmqFunctions<T> {
474550 . cmd ( "TIME" )
475551 . query_async ( conn)
476552 . await ?;
477-
553+
478554 #[ cfg( feature = "break-js-comp" ) ]
479555 let time = ( result. 1 ) . 0 * 1000000 + ( result. 1 ) . 1 ;
480556 #[ cfg( not( feature = "break-js-comp" ) ) ]
0 commit comments