@@ -145,6 +145,21 @@ describe('PineconeVectorStore', () => {
145145 await store . initialize ( ) ;
146146 expect ( fetchCalls . length ) . toBe ( count ) ;
147147 } ) ;
148+
149+ it ( 'retries throttled initialization checks with exponential backoff' , async ( ) => {
150+ vi . useFakeTimers ( ) ;
151+ fetchResponseQueue . push ( errResponse ( 429 , 'rate limited' ) ) ;
152+ fetchResponseQueue . push ( okJson ( { namespaces : { } , totalVectorCount : 0 } ) ) ;
153+ store = new PineconeVectorStore ( makeConfig ( ) ) ;
154+
155+ const initPromise = store . initialize ( ) ;
156+ await vi . runAllTimersAsync ( ) ;
157+ await initPromise ;
158+
159+ expect ( fetchCalls ) . toHaveLength ( 2 ) ;
160+ expect ( fetchCalls [ 0 ] . url ) . toContain ( '/describe_index_stats' ) ;
161+ expect ( fetchCalls [ 1 ] . url ) . toContain ( '/describe_index_stats' ) ;
162+ } ) ;
148163 } ) ;
149164
150165 // =========================================================================
@@ -550,6 +565,27 @@ describe('PineconeVectorStore', () => {
550565 expect ( result . deletedCount ) . toBe ( 3 ) ;
551566 } ) ;
552567
568+ it ( 'retries throttled ID deletes with exponential backoff' , async ( ) => {
569+ fetchResponseQueue . push ( okJson ( { } ) ) ; // init
570+ store = new PineconeVectorStore ( makeConfig ( ) ) ;
571+ await store . initialize ( ) ;
572+ resetMocks ( ) ;
573+ vi . useFakeTimers ( ) ;
574+
575+ fetchResponseQueue . push ( errResponse ( 429 , 'rate limited' ) ) ;
576+ fetchResponseQueue . push ( okJson ( { } ) ) ;
577+
578+ const resultPromise = store . delete ( 'ns' , [ 'a' , 'b' ] ) ;
579+
580+ await vi . runAllTimersAsync ( ) ;
581+ const result = await resultPromise ;
582+
583+ expect ( fetchCalls ) . toHaveLength ( 2 ) ;
584+ expect ( parseFetchBody ( fetchCalls [ 0 ] ) . ids ) . toEqual ( [ 'a' , 'b' ] ) ;
585+ expect ( parseFetchBody ( fetchCalls [ 1 ] ) . ids ) . toEqual ( [ 'a' , 'b' ] ) ;
586+ expect ( result . deletedCount ) . toBe ( 2 ) ;
587+ } ) ;
588+
553589 it ( 'deleteAll sends deleteAll=true' , async ( ) => {
554590 fetchResponseQueue . push ( okJson ( { } ) ) ; // init
555591 store = new PineconeVectorStore ( makeConfig ( ) ) ;
@@ -564,6 +600,27 @@ describe('PineconeVectorStore', () => {
564600 expect ( result . deletedCount ) . toBe ( - 1 ) ; // Pinecone doesn't return count.
565601 } ) ;
566602
603+ it ( 'retries throttled deleteAll requests with exponential backoff' , async ( ) => {
604+ fetchResponseQueue . push ( okJson ( { } ) ) ; // init
605+ store = new PineconeVectorStore ( makeConfig ( ) ) ;
606+ await store . initialize ( ) ;
607+ resetMocks ( ) ;
608+ vi . useFakeTimers ( ) ;
609+
610+ fetchResponseQueue . push ( errResponse ( 429 , 'rate limited' ) ) ;
611+ fetchResponseQueue . push ( okJson ( { } ) ) ;
612+
613+ const resultPromise = store . delete ( 'ns' , undefined , { deleteAll : true } ) ;
614+
615+ await vi . runAllTimersAsync ( ) ;
616+ const result = await resultPromise ;
617+
618+ expect ( fetchCalls ) . toHaveLength ( 2 ) ;
619+ expect ( parseFetchBody ( fetchCalls [ 0 ] ) . deleteAll ) . toBe ( true ) ;
620+ expect ( parseFetchBody ( fetchCalls [ 1 ] ) . deleteAll ) . toBe ( true ) ;
621+ expect ( result . deletedCount ) . toBe ( - 1 ) ;
622+ } ) ;
623+
567624 it ( 'deletes by metadata filter through /vectors/delete' , async ( ) => {
568625 fetchResponseQueue . push ( okJson ( { } ) ) ; // init
569626 store = new PineconeVectorStore ( makeConfig ( ) ) ;
@@ -711,9 +768,37 @@ describe('PineconeVectorStore', () => {
711768 store = new PineconeVectorStore ( makeConfig ( ) ) ;
712769 await store . initialize ( ) ;
713770 resetMocks ( ) ;
771+ vi . useFakeTimers ( ) ;
772+
773+ mockFetch
774+ . mockRejectedValueOnce ( new Error ( 'network error' ) )
775+ . mockRejectedValueOnce ( new Error ( 'network error' ) )
776+ . mockRejectedValueOnce ( new Error ( 'network error' ) )
777+ . mockRejectedValueOnce ( new Error ( 'network error' ) ) ;
778+
779+ const healthPromise = store . healthCheck ( ) ;
780+ await vi . runAllTimersAsync ( ) ;
714781
715- mockFetch . mockRejectedValueOnce ( new Error ( 'network error' ) ) ;
716- expect ( await store . healthCheck ( ) ) . toBe ( false ) ;
782+ expect ( await healthPromise ) . toBe ( false ) ;
783+ } ) ;
784+
785+ it ( 'retries throttled health checks with exponential backoff' , async ( ) => {
786+ fetchResponseQueue . push ( okJson ( { } ) ) ; // init
787+ store = new PineconeVectorStore ( makeConfig ( ) ) ;
788+ await store . initialize ( ) ;
789+ resetMocks ( ) ;
790+ vi . useFakeTimers ( ) ;
791+
792+ fetchResponseQueue . push ( errResponse ( 429 , 'rate limited' ) ) ;
793+ fetchResponseQueue . push ( okJson ( { namespaces : { } , totalVectorCount : 0 } ) ) ;
794+
795+ const healthPromise = store . healthCheck ( ) ;
796+ await vi . runAllTimersAsync ( ) ;
797+
798+ expect ( await healthPromise ) . toBe ( true ) ;
799+ expect ( fetchCalls ) . toHaveLength ( 2 ) ;
800+ expect ( fetchCalls [ 0 ] . url ) . toContain ( '/describe_index_stats' ) ;
801+ expect ( fetchCalls [ 1 ] . url ) . toContain ( '/describe_index_stats' ) ;
717802 } ) ;
718803 } ) ;
719804
0 commit comments