@@ -214,6 +214,17 @@ private CasbinRule savePolicyLine(String ptype, List<String> rule) {
214214 }
215215
216216 private void putCasbinRuleItem (CasbinRule line ) {
217+ Map <String , AttributeValue > item = buildItemFromCasbinRule (line );
218+
219+ PutItemRequest request = PutItemRequest .builder ()
220+ .tableName (TABLE_NAME )
221+ .item (item )
222+ .build ();
223+
224+ client .putItem (request );
225+ }
226+
227+ private Map <String , AttributeValue > buildItemFromCasbinRule (CasbinRule line ) {
217228 Map <String , AttributeValue > item = new HashMap <>();
218229 item .put ("ID" , AttributeValue .builder ().s (UUID .randomUUID ().toString ()).build ());
219230 item .put ("ptype" , AttributeValue .builder ().s (line .ptype != null ? line .ptype : "" ).build ());
@@ -223,27 +234,94 @@ private void putCasbinRuleItem(CasbinRule line) {
223234 item .put ("v3" , AttributeValue .builder ().s (line .v3 != null ? line .v3 : "" ).build ());
224235 item .put ("v4" , AttributeValue .builder ().s (line .v4 != null ? line .v4 : "" ).build ());
225236 item .put ("v5" , AttributeValue .builder ().s (line .v5 != null ? line .v5 : "" ).build ());
237+ return item ;
238+ }
239+
240+ private void writeBatchWithRetry (List <WriteRequest > writeRequests ) {
241+ List <WriteRequest > unprocessedItems = new ArrayList <>(writeRequests );
242+ int retryCount = 0 ;
243+ int maxRetries = 5 ;
244+ long initialBackoffMs = 50 ;
226245
227- PutItemRequest request = PutItemRequest .builder ()
228- .tableName (TABLE_NAME )
229- .item (item )
230- .build ();
246+ while (!unprocessedItems .isEmpty () && retryCount < maxRetries ) {
247+ Map <String , List <WriteRequest >> requestItems = new HashMap <>();
248+ requestItems .put (TABLE_NAME , unprocessedItems );
249+
250+ BatchWriteItemRequest batchRequest = BatchWriteItemRequest .builder ()
251+ .requestItems (requestItems )
252+ .build ();
253+
254+ BatchWriteItemResponse response = client .batchWriteItem (batchRequest );
255+
256+ // Get any unprocessed items for retry
257+ Map <String , List <WriteRequest >> unprocessed = response .unprocessedItems ();
258+ if (unprocessed != null && unprocessed .containsKey (TABLE_NAME )) {
259+ unprocessedItems = new ArrayList <>(unprocessed .get (TABLE_NAME ));
260+ retryCount ++;
261+
262+ if (!unprocessedItems .isEmpty ()) {
263+ // Exponential backoff
264+ long backoffMs = initialBackoffMs * (long ) Math .pow (2 , retryCount - 1 );
265+ try {
266+ Thread .sleep (backoffMs );
267+ } catch (InterruptedException e ) {
268+ Thread .currentThread ().interrupt ();
269+ throw new Error ("Interrupted during backoff" , e );
270+ }
271+ }
272+ } else {
273+ // All items processed successfully
274+ unprocessedItems .clear ();
275+ }
276+ }
231277
232- client .putItem (request );
278+ if (!unprocessedItems .isEmpty ()) {
279+ throw new Error ("Failed to write all items after " + maxRetries + " retries. " +
280+ unprocessedItems .size () + " items remaining." );
281+ }
282+ }
283+
284+ private void batchSaveRows (List <CasbinRule > rules ) {
285+ if (rules .isEmpty ()) {
286+ return ;
287+ }
288+
289+ int batchSize = 25 ; // DynamoDB batch write limit
290+ List <WriteRequest > batch = new ArrayList <>();
291+
292+ for (CasbinRule rule : rules ) {
293+ Map <String , AttributeValue > item = buildItemFromCasbinRule (rule );
294+ WriteRequest writeRequest = WriteRequest .builder ()
295+ .putRequest (PutRequest .builder ().item (item ).build ())
296+ .build ();
297+ batch .add (writeRequest );
298+
299+ if (batch .size () >= batchSize ) {
300+ writeBatchWithRetry (batch );
301+ batch .clear ();
302+ }
303+ }
304+
305+ // Write any remaining items
306+ if (!batch .isEmpty ()) {
307+ writeBatchWithRetry (batch );
308+ }
233309 }
234310
235311
236312 /**
237- * svePolicy saves all policy rules to the storage.
313+ * savePolicy saves all policy rules to the storage.
238314 */
239315 @ Override
240316 public void savePolicy (Model model ) {
317+ List <CasbinRule > allRules = new ArrayList <>();
318+
241319 for (Map .Entry <String , Assertion > entry : model .model .get ("p" ).entrySet ()) {
242320 String ptype = entry .getKey ();
243321 Assertion ast = entry .getValue ();
244322 for (List <String > rule : ast .policy ) {
245323 CasbinRule line = savePolicyLine (ptype , rule );
246- putCasbinRuleItem (line );
324+ allRules . add (line );
247325 }
248326 }
249327
@@ -252,9 +330,11 @@ public void savePolicy(Model model) {
252330 Assertion ast = entry .getValue ();
253331 for (List <String > rule : ast .policy ) {
254332 CasbinRule line = savePolicyLine (ptype , rule );
255- putCasbinRuleItem (line );
333+ allRules . add (line );
256334 }
257335 }
336+
337+ batchSaveRows (allRules );
258338 }
259339
260340 /**
0 commit comments