@@ -25,12 +25,7 @@ use tokio::net::TcpStream;
25
25
use tokio:: time:: { timeout, Duration } ;
26
26
27
27
static CONFIG : Lazy < ServerConfig > = Lazy :: new ( || ServerConfig :: default ( ) ) ;
28
- static AI_CONFIG : Lazy < AIProxyConfig > = Lazy :: new ( || {
29
- let mut ai_proxy = AIProxyConfig :: default ( ) . os_select_port ( ) ;
30
- ai_proxy. db_port = CONFIG . port . clone ( ) ;
31
- ai_proxy. db_host = CONFIG . host . clone ( ) ;
32
- ai_proxy
33
- } ) ;
28
+ static AI_CONFIG : Lazy < AIProxyConfig > = Lazy :: new ( || AIProxyConfig :: default ( ) . os_select_port ( ) ) ;
34
29
35
30
static PERSISTENCE_FILE : Lazy < PathBuf > =
36
31
Lazy :: new ( || PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "ahnlich_ai_proxy.dat" ) ) ;
@@ -89,7 +84,11 @@ async fn provision_test_servers() -> SocketAddr {
89
84
let server = Server :: new ( & CONFIG )
90
85
. await
91
86
. expect ( "Could not initialize server" ) ;
92
- let ai_server = AIProxyServer :: new ( & AI_CONFIG )
87
+ let db_port = server. local_addr ( ) . unwrap ( ) . port ( ) ;
88
+ let mut config = AI_CONFIG . clone ( ) ;
89
+ config. db_port = db_port;
90
+
91
+ let ai_server = AIProxyServer :: new ( config)
93
92
. await
94
93
. expect ( "Could not initialize ai proxy" ) ;
95
94
@@ -422,7 +421,7 @@ async fn test_ai_proxy_del_key_drop_store() {
422
421
423
422
#[ tokio:: test]
424
423
async fn test_ai_proxy_fails_db_server_unavailable ( ) {
425
- let ai_server = AIProxyServer :: new ( & AI_CONFIG )
424
+ let ai_server = AIProxyServer :: new ( AI_CONFIG . clone ( ) )
426
425
. await
427
426
. expect ( "Could not initialize ai proxy" ) ;
428
427
@@ -463,7 +462,7 @@ async fn test_ai_proxy_test_with_persistence() {
463
462
let server = Server :: new ( & CONFIG )
464
463
. await
465
464
. expect ( "Could not initialize server" ) ;
466
- let ai_server = AIProxyServer :: new ( & AI_CONFIG_WITH_PERSISTENCE )
465
+ let ai_server = AIProxyServer :: new ( AI_CONFIG_WITH_PERSISTENCE . clone ( ) )
467
466
. await
468
467
. expect ( "Could not initialize ai proxy" ) ;
469
468
@@ -515,7 +514,7 @@ async fn test_ai_proxy_test_with_persistence() {
515
514
tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
516
515
// start another server with existing persistence
517
516
518
- let persisted_server = AIProxyServer :: new ( & AI_CONFIG_WITH_PERSISTENCE )
517
+ let persisted_server = AIProxyServer :: new ( AI_CONFIG_WITH_PERSISTENCE . clone ( ) )
519
518
. await
520
519
. unwrap ( ) ;
521
520
@@ -583,3 +582,211 @@ async fn test_ai_proxy_destroy_database() {
583
582
let mut reader = BufReader :: new ( second_stream) ;
584
583
query_server_assert_result ( & mut reader, message, expected) . await
585
584
}
585
+
586
+ #[ tokio:: test]
587
+ async fn test_ai_proxy_binary_store_actions ( ) {
588
+ let address = provision_test_servers ( ) . await ;
589
+
590
+ let store_name = StoreName ( String :: from ( "Deven Image Store" ) ) ;
591
+ let matching_metadatakey = MetadataKey :: new ( "Name" . to_owned ( ) ) ;
592
+ let matching_metadatavalue = MetadataValue :: RawString ( "Greatness" . to_owned ( ) ) ;
593
+
594
+ let store_value_1 =
595
+ StoreValue :: from_iter ( [ ( matching_metadatakey. clone ( ) , matching_metadatavalue. clone ( ) ) ] ) ;
596
+ let store_value_2 = StoreValue :: from_iter ( [ (
597
+ matching_metadatakey. clone ( ) ,
598
+ MetadataValue :: RawString ( "Deven" . to_owned ( ) ) ,
599
+ ) ] ) ;
600
+ let store_data = vec ! [
601
+ (
602
+ StoreInput :: Binary ( vec![ 93 , 4 , 1 , 6 , 2 , 8 , 8 , 32 , 45 ] ) ,
603
+ store_value_1. clone( ) ,
604
+ ) ,
605
+ (
606
+ StoreInput :: Binary ( vec![ 102 , 3 , 4 , 6 , 7 , 8 , 4 , 190 ] ) ,
607
+ store_value_2. clone( ) ,
608
+ ) ,
609
+ (
610
+ StoreInput :: Binary ( vec![ 211 , 2 , 4 , 6 , 7 , 8 , 8 , 92 , 21 , 10 ] ) ,
611
+ StoreValue :: from_iter( [ (
612
+ matching_metadatakey. clone( ) ,
613
+ MetadataValue :: RawString ( "Daniel" . to_owned( ) ) ,
614
+ ) ] ) ,
615
+ ) ,
616
+ ] ;
617
+
618
+ let message = AIServerQuery :: from_queries ( & [
619
+ AIQuery :: CreateStore {
620
+ r#type : AIStoreType :: Binary ,
621
+ store : store_name. clone ( ) ,
622
+ model : AIModel :: Llama3 ,
623
+ predicates : HashSet :: new ( ) ,
624
+ non_linear_indices : HashSet :: new ( ) ,
625
+ } ,
626
+ AIQuery :: ListStores ,
627
+ AIQuery :: CreatePredIndex {
628
+ store : store_name. clone ( ) ,
629
+ predicates : HashSet :: from_iter ( [
630
+ MetadataKey :: new ( "Name" . to_string ( ) ) ,
631
+ MetadataKey :: new ( "Age" . to_string ( ) ) ,
632
+ ] ) ,
633
+ } ,
634
+ AIQuery :: Set {
635
+ store : store_name. clone ( ) ,
636
+ inputs : store_data,
637
+ } ,
638
+ AIQuery :: DropPredIndex {
639
+ store : store_name. clone ( ) ,
640
+ predicates : HashSet :: from_iter ( [ MetadataKey :: new ( "Age" . to_string ( ) ) ] ) ,
641
+ error_if_not_exists : true ,
642
+ } ,
643
+ AIQuery :: GetPred {
644
+ store : store_name. clone ( ) ,
645
+ condition : PredicateCondition :: Value ( Predicate :: Equals {
646
+ key : matching_metadatakey. clone ( ) ,
647
+ value : matching_metadatavalue,
648
+ } ) ,
649
+ } ,
650
+ AIQuery :: PurgeStores ,
651
+ ] ) ;
652
+
653
+ let mut expected = AIServerResult :: with_capacity ( 7 ) ;
654
+
655
+ expected. push ( Ok ( AIServerResponse :: Unit ) ) ;
656
+ expected. push ( Ok ( AIServerResponse :: StoreList ( HashSet :: from_iter ( [
657
+ AIStoreInfo {
658
+ name : store_name,
659
+ r#type : AIStoreType :: Binary ,
660
+ model : AIModel :: Llama3 ,
661
+ embedding_size : AIModel :: Llama3 . embedding_size ( ) . into ( ) ,
662
+ } ,
663
+ ] ) ) ) ) ;
664
+ expected. push ( Ok ( AIServerResponse :: CreateIndex ( 2 ) ) ) ;
665
+ expected. push ( Ok ( AIServerResponse :: Set ( StoreUpsert {
666
+ inserted : 3 ,
667
+ updated : 0 ,
668
+ } ) ) ) ;
669
+ expected. push ( Ok ( AIServerResponse :: Del ( 1 ) ) ) ;
670
+ expected. push ( Ok ( AIServerResponse :: Get ( vec ! [ (
671
+ StoreInput :: Binary ( vec![ 93 , 4 , 1 , 6 , 2 , 8 , 8 , 32 , 45 ] ) ,
672
+ store_value_1. clone( ) ,
673
+ ) ] ) ) ) ;
674
+ expected. push ( Ok ( AIServerResponse :: Del ( 1 ) ) ) ;
675
+
676
+ let connected_stream = TcpStream :: connect ( address) . await . unwrap ( ) ;
677
+ let mut reader = BufReader :: new ( connected_stream) ;
678
+
679
+ query_server_assert_result ( & mut reader, message, expected) . await ;
680
+ }
681
+
682
+ #[ tokio:: test]
683
+ async fn test_ai_proxy_binary_store_with_text_and_binary ( ) {
684
+ let address = provision_test_servers ( ) . await ;
685
+
686
+ let store_name = StoreName ( String :: from ( "Deven Mixed Store" ) ) ;
687
+ let matching_metadatakey = MetadataKey :: new ( "Brand" . to_owned ( ) ) ;
688
+ let matching_metadatavalue = MetadataValue :: RawString ( "Nike" . to_owned ( ) ) ;
689
+
690
+ let store_value_1 =
691
+ StoreValue :: from_iter ( [ ( matching_metadatakey. clone ( ) , matching_metadatavalue. clone ( ) ) ] ) ;
692
+ let store_value_2 = StoreValue :: from_iter ( [ (
693
+ matching_metadatakey. clone ( ) ,
694
+ MetadataValue :: RawString ( "Deven" . to_owned ( ) ) ,
695
+ ) ] ) ;
696
+ let store_data = vec ! [
697
+ (
698
+ StoreInput :: Binary ( vec![ 93 , 4 , 1 , 6 , 2 , 8 , 8 , 32 , 45 ] ) ,
699
+ store_value_1. clone( ) ,
700
+ ) ,
701
+ (
702
+ StoreInput :: Binary ( vec![ 102 , 3 , 4 , 6 , 7 , 8 , 4 , 190 ] ) ,
703
+ store_value_2. clone( ) ,
704
+ ) ,
705
+ (
706
+ StoreInput :: Binary ( vec![ 211 , 2 , 4 , 6 , 7 , 8 , 8 , 92 , 21 , 10 ] ) ,
707
+ StoreValue :: from_iter( [ (
708
+ matching_metadatakey. clone( ) ,
709
+ MetadataValue :: RawString ( "Daniel" . to_owned( ) ) ,
710
+ ) ] ) ,
711
+ ) ,
712
+ (
713
+ StoreInput :: RawString ( String :: from( "Buster Matthews is the name" ) ) ,
714
+ StoreValue :: from_iter( [ (
715
+ MetadataKey :: new( "Description" . to_string( ) ) ,
716
+ MetadataValue :: RawString ( "20 year old line backer" . to_owned( ) ) ,
717
+ ) ] ) ,
718
+ ) ,
719
+ ] ;
720
+
721
+ let message = AIServerQuery :: from_queries ( & [
722
+ AIQuery :: CreateStore {
723
+ r#type : AIStoreType :: Binary ,
724
+ store : store_name. clone ( ) ,
725
+ model : AIModel :: Llama3 ,
726
+ predicates : HashSet :: new ( ) ,
727
+ non_linear_indices : HashSet :: new ( ) ,
728
+ } ,
729
+ AIQuery :: ListStores ,
730
+ AIQuery :: CreatePredIndex {
731
+ store : store_name. clone ( ) ,
732
+ predicates : HashSet :: from_iter ( [
733
+ MetadataKey :: new ( "Name" . to_string ( ) ) ,
734
+ MetadataKey :: new ( "Description" . to_string ( ) ) ,
735
+ ] ) ,
736
+ } ,
737
+ AIQuery :: Set {
738
+ store : store_name. clone ( ) ,
739
+ inputs : store_data,
740
+ } ,
741
+ AIQuery :: DropPredIndex {
742
+ store : store_name. clone ( ) ,
743
+ predicates : HashSet :: from_iter ( [ MetadataKey :: new ( "Age" . to_string ( ) ) ] ) ,
744
+ error_if_not_exists : true ,
745
+ } ,
746
+ AIQuery :: GetPred {
747
+ store : store_name. clone ( ) ,
748
+ condition : PredicateCondition :: Value ( Predicate :: In {
749
+ key : MetadataKey :: new ( "Description" . to_owned ( ) ) ,
750
+ value : HashSet :: from_iter ( [ MetadataValue :: RawString (
751
+ "20 year old line backer" . to_owned ( ) ,
752
+ ) ] ) ,
753
+ } ) ,
754
+ } ,
755
+ AIQuery :: PurgeStores ,
756
+ ] ) ;
757
+
758
+ let mut expected = AIServerResult :: with_capacity ( 7 ) ;
759
+
760
+ expected. push ( Ok ( AIServerResponse :: Unit ) ) ;
761
+ expected. push ( Ok ( AIServerResponse :: StoreList ( HashSet :: from_iter ( [
762
+ AIStoreInfo {
763
+ name : store_name,
764
+ r#type : AIStoreType :: Binary ,
765
+ model : AIModel :: Llama3 ,
766
+ embedding_size : AIModel :: Llama3 . embedding_size ( ) . into ( ) ,
767
+ } ,
768
+ ] ) ) ) ) ;
769
+ expected. push ( Ok ( AIServerResponse :: CreateIndex ( 2 ) ) ) ;
770
+ expected. push ( Ok ( AIServerResponse :: Set ( StoreUpsert {
771
+ inserted : 4 ,
772
+ updated : 0 ,
773
+ } ) ) ) ;
774
+ expected. push ( Err (
775
+ "db error Predicate Age not found in store, attempt CREATEPREDINDEX with predicate"
776
+ . to_string ( ) ,
777
+ ) ) ;
778
+
779
+ expected. push ( Ok ( AIServerResponse :: Get ( vec ! [ (
780
+ StoreInput :: RawString ( String :: from( "Buster Matthews is the name" ) ) ,
781
+ StoreValue :: from_iter( [ (
782
+ MetadataKey :: new( "Description" . to_owned( ) ) ,
783
+ MetadataValue :: RawString ( "20 year old line backer" . to_owned( ) ) ,
784
+ ) ] ) ,
785
+ ) ] ) ) ) ;
786
+ expected. push ( Ok ( AIServerResponse :: Del ( 1 ) ) ) ;
787
+
788
+ let connected_stream = TcpStream :: connect ( address) . await . unwrap ( ) ;
789
+ let mut reader = BufReader :: new ( connected_stream) ;
790
+
791
+ query_server_assert_result ( & mut reader, message, expected) . await ;
792
+ }
0 commit comments