@@ -27,7 +27,19 @@ const KEY_COLUMN: &str = "key";
2727const VALUE_COLUMN : & str = "value" ;
2828const VERSION_COLUMN : & str = "version" ;
2929
30- const LIST_KEY_VERSIONS_MAX_PAGE_SIZE : i32 = 100 ;
30+ /// The maximum number of key versions that can be returned in a single page.
31+ ///
32+ /// This constant helps control memory and bandwidth usage for list operations,
33+ /// preventing overly large payloads. If the number of results exceeds this limit,
34+ /// the response will be paginated.
35+ pub const LIST_KEY_VERSIONS_MAX_PAGE_SIZE : i32 = 100 ;
36+
37+ /// The maximum number of items allowed in a single `PutObjectRequest`.
38+ ///
39+ /// Setting an upper bound on the number of items helps ensure that
40+ /// each request stays within acceptable memory and performance limits.
41+ /// Exceeding this value will result in request rejection through [`VssError::InvalidRequestError`].
42+ pub const MAX_PUT_REQUEST_ITEM_COUNT : usize = 1000 ;
3143
3244/// A [PostgreSQL](https://www.postgresql.org/) based backend implementation for VSS.
3345pub struct PostgresBackendImpl {
@@ -47,12 +59,12 @@ impl PostgresBackendImpl {
4759 Ok ( PostgresBackendImpl { pool } )
4860 }
4961
50- fn build_vss_record ( & self , user_token : & str , store_id : & str , kv : & KeyValue ) -> VssDbRecord {
62+ fn build_vss_record ( & self , user_token : String , store_id : String , kv : KeyValue ) -> VssDbRecord {
5163 let now = Utc :: now ( ) ;
5264 VssDbRecord {
53- user_token : user_token . to_string ( ) ,
54- store_id : store_id . to_string ( ) ,
55- key : kv. key . clone ( ) ,
65+ user_token,
66+ store_id,
67+ key : kv. key ,
5668 value : kv. value . to_vec ( ) ,
5769 version : kv. version ,
5870 created_at : now,
@@ -227,28 +239,30 @@ impl KvStore for PostgresBackendImpl {
227239 & self , user_token : String , request : PutObjectRequest ,
228240 ) -> Result < PutObjectResponse , VssError > {
229241 let store_id = & request. store_id ;
230- if request. transaction_items . len ( ) + request. delete_items . len ( ) > 1000 {
231- return Err ( VssError :: InvalidRequestError (
232- "Number of write items per request should be less than equal to 1000" . to_string ( ) ,
233- ) ) ;
242+ if request. transaction_items . len ( ) + request. delete_items . len ( ) > MAX_PUT_REQUEST_ITEM_COUNT
243+ {
244+ return Err ( VssError :: InvalidRequestError ( format ! (
245+ "Number of write items per request should be less than equal to {}" ,
246+ MAX_PUT_REQUEST_ITEM_COUNT
247+ ) ) ) ;
234248 }
235249 let mut vss_put_records: Vec < VssDbRecord > = request
236250 . transaction_items
237- . iter ( )
238- . map ( |kv| self . build_vss_record ( & user_token, store_id, kv) )
251+ . into_iter ( )
252+ . map ( |kv| self . build_vss_record ( user_token. to_string ( ) , store_id. to_string ( ) , kv) )
239253 . collect ( ) ;
240254
241255 let vss_delete_records: Vec < VssDbRecord > = request
242256 . delete_items
243- . iter ( )
244- . map ( |kv| self . build_vss_record ( & user_token, store_id, kv) )
257+ . into_iter ( )
258+ . map ( |kv| self . build_vss_record ( user_token. to_string ( ) , store_id. to_string ( ) , kv) )
245259 . collect ( ) ;
246260
247261 if let Some ( global_version) = request. global_version {
248262 let global_version_record = self . build_vss_record (
249- & user_token,
250- store_id,
251- & KeyValue {
263+ user_token,
264+ store_id. to_string ( ) ,
265+ KeyValue {
252266 key : GLOBAL_VERSION_KEY . to_string ( ) ,
253267 value : Bytes :: new ( ) ,
254268 version : global_version,
@@ -300,7 +314,10 @@ impl KvStore for PostgresBackendImpl {
300314 & self , user_token : String , request : DeleteObjectRequest ,
301315 ) -> Result < DeleteObjectResponse , VssError > {
302316 let store_id = & request. store_id ;
303- let vss_record = self . build_vss_record ( & user_token, store_id, & request. key_value . unwrap ( ) ) ;
317+ let key_value = request. key_value . ok_or_else ( || {
318+ VssError :: InvalidRequestError ( "key_value missing in DeleteObjectRequest" . to_string ( ) )
319+ } ) ?;
320+ let vss_record = self . build_vss_record ( user_token, store_id. to_string ( ) , key_value) ;
304321
305322 let mut conn = self
306323 . pool
@@ -362,7 +379,7 @@ impl KvStore for PostgresBackendImpl {
362379 let key_like = format ! ( "{}%" , key_prefix. as_deref( ) . unwrap_or( "" ) ) ;
363380 let page_token_param = page_token. as_deref ( ) . unwrap_or ( "" ) ;
364381 let params: Vec < & ( dyn tokio_postgres:: types:: ToSql + Sync ) > =
365- vec ! [ & user_token, & store_id, & page_token_param, & key_like, & ( limit) ] ;
382+ vec ! [ & user_token, & store_id, & page_token_param, & key_like, & limit] ;
366383
367384 let rows = conn
368385 . query ( stmt, & params)
0 commit comments