@@ -143,7 +143,6 @@ import { connectionIdentifier } from "./connection-name-identifier";
143143import { annotateToolResultOutcome } from "./tool-result" ;
144144
145145const PLUGIN_STORAGE_DELETE_KEY_BATCH_SIZE = 90 ;
146- const PLUGIN_STORAGE_CREATE_ROW_BATCH_SIZE = 90 ;
147146const MAX_APPROVAL_ARGUMENT_PREVIEW_CHARS = 4_000 ;
148147
149148// ---------------------------------------------------------------------------
@@ -601,6 +600,14 @@ type LooseStorageDb = {
601600 tableName : string ,
602601 rows : readonly Record < string , unknown > [ ] ,
603602 ) => Promise < readonly unknown [ ] > ;
603+ readonly upsertMany : (
604+ tableName : string ,
605+ options : {
606+ readonly target : readonly string [ ] ;
607+ readonly update : readonly string [ ] ;
608+ readonly values : readonly Record < string , unknown > [ ] ;
609+ } ,
610+ ) => Promise < void > ;
604611 readonly deleteMany : ( tableName : string , options ?: unknown ) => Promise < void > ;
605612 readonly findFirst : (
606613 tableName : string ,
@@ -637,6 +644,19 @@ const makeCoreDb = (fuma: ReturnType<typeof makeFumaClient>) => ({
637644 : fuma
638645 . use ( `${ tableName } .createMany` , ( db ) => asLooseStorageDb ( db ) . createMany ( tableName , rows ) )
639646 . pipe ( Effect . asVoid ) ,
647+ upsertMany : < TName extends CoreTableName > (
648+ tableName : TName ,
649+ options : {
650+ readonly target : readonly string [ ] ;
651+ readonly update : readonly string [ ] ;
652+ readonly values : readonly Record < string , unknown > [ ] ;
653+ } ,
654+ ) : Effect . Effect < void , StorageFailure > =>
655+ options . values . length === 0
656+ ? Effect . void
657+ : fuma . use ( `${ tableName } .upsertMany` , ( db ) =>
658+ asLooseStorageDb ( db ) . upsertMany ( tableName , options ) ,
659+ ) ,
640660 deleteMany : < TName extends CoreTableName > (
641661 tableName : TName ,
642662 options : { readonly where ?: CoreWhere } = { } ,
@@ -986,33 +1006,22 @@ const makePluginStorageFacade = (input: {
9861006 const uniqueEntries = [ ...entriesById . values ( ) ] ;
9871007 if ( uniqueEntries . length === 0 ) return ;
9881008
989- yield * deleteManyImpl ( owner , os . subject , uniqueEntries ) ;
990-
9911009 const now = new Date ( ) ;
992- for (
993- let offset = 0 ;
994- offset < uniqueEntries . length ;
995- offset += PLUGIN_STORAGE_CREATE_ROW_BATCH_SIZE
996- ) {
997- const batchEntries = uniqueEntries . slice (
998- offset ,
999- offset + PLUGIN_STORAGE_CREATE_ROW_BATCH_SIZE ,
1000- ) ;
1001- yield * input . core . createMany (
1002- "plugin_storage" ,
1003- batchEntries . map ( ( entry ) => ( {
1004- tenant,
1005- owner : os . owner ,
1006- subject : os . subject ,
1007- plugin_id : input . pluginId ,
1008- collection : entry . collection ,
1009- key : entry . key ,
1010- data : entry . data ,
1011- created_at : now ,
1012- updated_at : now ,
1013- } ) ) ,
1014- ) ;
1015- }
1010+ yield * input . core . upsertMany ( "plugin_storage" , {
1011+ target : [ "tenant" , "owner" , "subject" , "plugin_id" , "collection" , "key" ] ,
1012+ update : [ "data" , "updated_at" ] ,
1013+ values : uniqueEntries . map ( ( entry ) => ( {
1014+ tenant,
1015+ owner : os . owner ,
1016+ subject : os . subject ,
1017+ plugin_id : input . pluginId ,
1018+ collection : entry . collection ,
1019+ key : entry . key ,
1020+ data : entry . data ,
1021+ created_at : now ,
1022+ updated_at : now ,
1023+ } ) ) ,
1024+ } ) ;
10161025 } ) ;
10171026
10181027 const removeManyImpl = (
@@ -1109,10 +1118,24 @@ const makePluginStorageFacade = (input: {
11091118 PluginStorageEntry < PluginStorageCollectionData < typeof definition > > ,
11101119 StorageFailure
11111120 > ,
1121+ putMany : ( storageInput ) =>
1122+ putManyImpl (
1123+ storageInput . owner ,
1124+ storageInput . entries . map ( ( entry ) => ( {
1125+ collection : definition . name ,
1126+ key : entry . key ,
1127+ data : entry . data ,
1128+ } ) ) ,
1129+ ) ,
11121130 query : ( storageInput ) => queryCollection ( definition , storageInput ) ,
11131131 count : ( storageInput ) =>
11141132 queryCollection ( definition , storageInput ) . pipe ( Effect . map ( ( rows ) => rows . length ) ) ,
11151133 remove : ( storageInput ) => removeImpl ( storageInput . owner , definition . name , storageInput . key ) ,
1134+ removeMany : ( storageInput ) =>
1135+ removeManyImpl (
1136+ storageInput . owner ,
1137+ storageInput . keys . map ( ( key ) => ( { collection : definition . name , key } ) ) ,
1138+ ) ,
11161139 } ) ,
11171140 get : ( storageInput ) => getVisible ( storageInput . collection , storageInput . key ) ,
11181141 getForOwner : ( storageInput ) =>
0 commit comments