7
7
use hashbrown:: HashMap ;
8
8
use rand:: distributions:: Alphanumeric ;
9
9
use rand:: { thread_rng, Rng } ;
10
+ use std:: path:: Path ;
10
11
use std:: str:: { self , SplitWhitespace } ;
11
12
use std:: vec:: Vec ;
12
13
@@ -15,6 +16,7 @@ use super::statistics::ChannelStatistics;
15
16
use crate :: query:: builder:: { QueryBuilder , QueryBuilderResult } ;
16
17
use crate :: query:: types:: { QueryGenericLang , QuerySearchLimit , QuerySearchOffset } ;
17
18
use crate :: store:: fst:: StoreFSTPool ;
19
+ use crate :: store:: kv:: StoreKVPool ;
18
20
use crate :: store:: operation:: StoreOperationDispatch ;
19
21
use crate :: APP_CONF ;
20
22
@@ -64,7 +66,8 @@ lazy_static! {
64
66
vec![ "PUSH" , "POP" , "COUNT" , "FLUSHC" , "FLUSHB" , "FLUSHO" , "PING" , "HELP" , "QUIT" ] ;
65
67
pub static ref COMMANDS_MODE_CONTROL : Vec <& ' static str > =
66
68
vec![ "TRIGGER" , "INFO" , "PING" , "HELP" , "QUIT" ] ;
67
- pub static ref CONTROL_TRIGGER_ACTIONS : Vec <& ' static str > = vec![ "consolidate" ] ;
69
+ pub static ref CONTROL_TRIGGER_ACTIONS : Vec <& ' static str > =
70
+ vec![ "consolidate" , "backup" , "restore" ] ;
68
71
static ref MANUAL_MODE_SEARCH : HashMap <& ' static str , & ' static Vec <& ' static str >> =
69
72
[ ( "commands" , & * COMMANDS_MODE_SEARCH ) ]
70
73
. iter( )
@@ -776,26 +779,60 @@ impl ChannelCommandIngest {
776
779
777
780
impl ChannelCommandControl {
778
781
pub fn dispatch_trigger ( mut parts : SplitWhitespace ) -> ChannelResult {
779
- match ( parts. next ( ) , parts. next ( ) ) {
780
- ( None , _) => Ok ( vec ! [ ChannelCommandResponse :: Result ( format!(
782
+ match ( parts. next ( ) , parts. next ( ) , parts . next ( ) ) {
783
+ ( None , _, _ ) => Ok ( vec ! [ ChannelCommandResponse :: Result ( format!(
781
784
"actions({})" ,
782
785
CONTROL_TRIGGER_ACTIONS . join( ", " )
783
786
) ) ] ) ,
784
- ( Some ( action_key) , next_part) => {
785
- if next_part. is_none ( ) {
786
- let action_key_lower = action_key. to_lowercase ( ) ;
787
+ ( Some ( action_key) , data_part, last_part) => {
788
+ let action_key_lower = action_key. to_lowercase ( ) ;
787
789
788
- match action_key_lower. as_str ( ) {
789
- "consolidate" => {
790
+ match action_key_lower. as_str ( ) {
791
+ "consolidate" => {
792
+ if data_part. is_none ( ) {
790
793
// Force a FST consolidate
791
794
StoreFSTPool :: consolidate ( true ) ;
792
795
793
796
Ok ( vec ! [ ChannelCommandResponse :: Ok ] )
797
+ } else {
798
+ Err ( ChannelCommandError :: InvalidFormat ( "TRIGGER consolidate" ) )
794
799
}
795
- _ => Err ( ChannelCommandError :: NotFound ) ,
796
800
}
797
- } else {
798
- Err ( ChannelCommandError :: InvalidFormat ( "TRIGGER [<action>]?" ) )
801
+ "backup" => {
802
+ match ( data_part, last_part) {
803
+ ( Some ( path) , None ) => {
804
+ // Proceed KV + FST backup
805
+ let path = Path :: new ( path) ;
806
+
807
+ if StoreKVPool :: backup ( path) . is_ok ( )
808
+ && StoreFSTPool :: backup ( path) . is_ok ( )
809
+ {
810
+ Ok ( vec ! [ ChannelCommandResponse :: Ok ] )
811
+ } else {
812
+ Err ( ChannelCommandError :: InternalError )
813
+ }
814
+ }
815
+ _ => Err ( ChannelCommandError :: InvalidFormat ( "TRIGGER backup <path>" ) ) ,
816
+ }
817
+ }
818
+ "restore" => {
819
+ match ( data_part, last_part) {
820
+ ( Some ( path) , None ) => {
821
+ // Proceed KV + FST restore
822
+ let path = Path :: new ( path) ;
823
+
824
+ if StoreKVPool :: restore ( path) . is_ok ( )
825
+ && StoreFSTPool :: restore ( path) . is_ok ( )
826
+ {
827
+ Ok ( vec ! [ ChannelCommandResponse :: Ok ] )
828
+ } else {
829
+ Err ( ChannelCommandError :: InternalError )
830
+ }
831
+ }
832
+ _ => Err ( ChannelCommandError :: InvalidFormat ( "TRIGGER restore <path>" ) ) ,
833
+ }
834
+ }
835
+ _ => Err ( ChannelCommandError :: NotFound ) ,
799
836
}
800
837
}
801
838
}
0 commit comments