From b35860e155a4383559f1c8845a8359cced93f146 Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Tue, 28 Oct 2025 13:50:17 +0530 Subject: [PATCH 1/5] feature: Added Safe Bulk Record Update with Progress Tracking snippet --- .../Safe Bulk Update with Logging/README.md | 94 +++++++++++++++++++ .../bulk_update_with_progress.js | 60 ++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md create mode 100644 Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md new file mode 100644 index 0000000000..9730e4105c --- /dev/null +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md @@ -0,0 +1,94 @@ +# Safe Bulk Record Update with Logging + +## Overview +Efficiently update multiple records in batch with error handling, progress tracking, and logging to prevent timeouts and data loss. + +## What It Does +- Updates records in configurable batch sizes +- Logs progress for monitoring +- Handles individual record errors without stopping batch +- Prevents script timeout with batch processing +- Tracks success/failure counts +- Logs detailed error information + +## Use Cases +- Bulk data migrations +- Mass field updates after deployment +- Scheduled bulk corrections +- Data cleanup operations +- Batch status updates across records + +## Files +- `bulk_update_with_progress.js` - Background Script for safe bulk updates + +## How to Use + +### Option 1: Run as Background Script +1. Go to **System Diagnostics > Script Background** +2. Copy code from `bulk_update_with_progress.js` +3. Modify the table name and query filter +4. Execute and monitor logs + +### Option 2: Create as Scheduled Job +1. Go to **System Scheduler > Scheduled Jobs** +2. Create new job with the script code +3. Schedule for off-peak hours +4. Logs will be available in System Logs + +## Example Usage +```javascript +// Customize these variables: +var TABLE = 'incident'; +var FILTER = "priority=1^state=2"; // Your query condition +var BATCH_SIZE = 100; +var FIELD_TO_UPDATE = 'assignment_group'; // Field to update +var NEW_VALUE = '123456789abc'; // New value + +// Run the script - it handles everything else +``` + +## Key Features +- **Batch Processing**: Prevents timeout by processing records in chunks +- **Error Resilience**: Continues on error, logs details +- **Progress Tracking**: Logs every N records updated +- **Flexible**: Works with any table and field +- **Safe**: Won't crash on individual record failures +- **Auditable**: Detailed logging of all operations + +## Output Examples +``` +[Bulk Update Started] Processing incidents with filter: priority=1 +[Progress] Updated 100 records successfully (5 errors) +[Progress] Updated 200 records successfully (8 errors) +[Bulk Update Complete] Total: 250 | Success: 242 | Errors: 8 +[Failed Records] 7af24b9c: User already has assignment +[Failed Records] 8bd35c8d: Invalid assignment group +``` + +## Performance Notes +- Batch size of 100 is optimal for most tables +- Adjust batch size based on available resources +- Run during maintenance windows for large updates +- Monitor system logs during execution + +## Customization +```javascript +// Change batch size for your table size +var BATCH_SIZE = 50; // For smaller batches +var BATCH_SIZE = 200; // For larger tables + +// Different field update logic +record.setValue(FIELD_TO_UPDATE, NEW_VALUE); +// Or use gs.getProperty() for configuration +``` + +## Requirements +- ServiceNow instance +- Access to Background Scripts or Scheduled Jobs +- Write access to target table +- Appropriate table and field permissions + +## Related APIs +- [GlideRecord Query API](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_UsingGlideRecord.html) +- [GlideSystem Logging](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_SystemLog.html) +- [Best Practices for Bulk Operations](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_BulkOperations.html) diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js new file mode 100644 index 0000000000..53792a560e --- /dev/null +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js @@ -0,0 +1,60 @@ +// Background Script: Safe Bulk Record Update with Progress Tracking +// Purpose: Update multiple records safely with batch processing and error handling + +var TABLE = 'incident'; // Change to your table +var FILTER = "priority=1"; // Add your filter conditions +var BATCH_SIZE = 100; +var FIELD_TO_UPDATE = 'state'; // Field to update +var NEW_VALUE = '1'; // Value to set + +var successCount = 0; +var errorCount = 0; +var totalProcessed = 0; + +gs.log('[Bulk Update Started] Table: ' + TABLE + ' | Filter: ' + FILTER, 'BulkUpdate'); + +try { + var gr = new GlideRecord(TABLE); + gr.addEncodedQuery(FILTER); + gr.query(); + + var recordsToProcess = []; + while (gr.next()) { + recordsToProcess.push(gr.getUniqueValue()); + + // Process in batches to prevent timeout + if (recordsToProcess.length === BATCH_SIZE) { + processBatch(recordsToProcess); + recordsToProcess = []; + } + } + + // Process remaining records + if (recordsToProcess.length > 0) { + processBatch(recordsToProcess); + } + + gs.log('[Bulk Update Complete] Total: ' + totalProcessed + ' | Success: ' + successCount + ' | Errors: ' + errorCount, 'BulkUpdate'); + +} catch (e) { + gs.error('[Bulk Update Error] ' + e.toString(), 'BulkUpdate'); +} + +function processBatch(recordIds) { + for (var i = 0; i < recordIds.length; i++) { + try { + var record = new GlideRecord(TABLE); + record.get(recordIds[i]); + record.setValue(FIELD_TO_UPDATE, NEW_VALUE); + record.update(); + successCount++; + } catch (error) { + errorCount++; + gs.log('[Failed Record] ' + recordIds[i] + ': ' + error.toString(), 'BulkUpdate'); + } + totalProcessed++; + } + + // Log progress + gs.log('[Progress] Updated ' + totalProcessed + ' records | Success: ' + successCount + ' | Errors: ' + errorCount, 'BulkUpdate'); +} From 223bb7bde413b2d9dae337633efdf9991ab6a82a Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Wed, 29 Oct 2025 09:19:16 +0530 Subject: [PATCH 2/5] fixed: Optimized bulk update to use updateMultiple and reduce database queries --- .../bulk_update_with_progress.js | 52 ++++++------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js index 53792a560e..cac9476f32 100644 --- a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js @@ -1,60 +1,40 @@ // Background Script: Safe Bulk Record Update with Progress Tracking -// Purpose: Update multiple records safely with batch processing and error handling +// Purpose: Update multiple records efficiently using updateMultiple() var TABLE = 'incident'; // Change to your table var FILTER = "priority=1"; // Add your filter conditions -var BATCH_SIZE = 100; var FIELD_TO_UPDATE = 'state'; // Field to update var NEW_VALUE = '1'; // Value to set var successCount = 0; var errorCount = 0; -var totalProcessed = 0; -gs.log('[Bulk Update Started] Table: ' + TABLE + ' | Filter: ' + FILTER, 'BulkUpdate'); +gs.info('[Bulk Update Started] Table: ' + TABLE + ' | Filter: ' + FILTER, 'BulkUpdate'); try { var gr = new GlideRecord(TABLE); gr.addEncodedQuery(FILTER); gr.query(); - var recordsToProcess = []; + // Collect all record IDs first (single query) + var recordIds = []; while (gr.next()) { - recordsToProcess.push(gr.getUniqueValue()); - - // Process in batches to prevent timeout - if (recordsToProcess.length === BATCH_SIZE) { - processBatch(recordsToProcess); - recordsToProcess = []; - } + recordIds.push(gr.getUniqueValue()); } - // Process remaining records - if (recordsToProcess.length > 0) { - processBatch(recordsToProcess); + // Update all records at once using updateMultiple + if (recordIds.length > 0) { + var updateGr = new GlideRecord(TABLE); + updateGr.addEncodedQuery(FILTER); + updateGr.setValue(FIELD_TO_UPDATE, NEW_VALUE); + updateGr.updateMultiple(); + + successCount = recordIds.length; + gs.info('[Bulk Update Complete] Total Updated: ' + successCount, 'BulkUpdate'); + } else { + gs.info('[Bulk Update] No records matched the filter criteria', 'BulkUpdate'); } - gs.log('[Bulk Update Complete] Total: ' + totalProcessed + ' | Success: ' + successCount + ' | Errors: ' + errorCount, 'BulkUpdate'); - } catch (e) { gs.error('[Bulk Update Error] ' + e.toString(), 'BulkUpdate'); } - -function processBatch(recordIds) { - for (var i = 0; i < recordIds.length; i++) { - try { - var record = new GlideRecord(TABLE); - record.get(recordIds[i]); - record.setValue(FIELD_TO_UPDATE, NEW_VALUE); - record.update(); - successCount++; - } catch (error) { - errorCount++; - gs.log('[Failed Record] ' + recordIds[i] + ': ' + error.toString(), 'BulkUpdate'); - } - totalProcessed++; - } - - // Log progress - gs.log('[Progress] Updated ' + totalProcessed + ' records | Success: ' + successCount + ' | Errors: ' + errorCount, 'BulkUpdate'); -} From 26ec6f08ee286176adcb0fe9163e0e241d445cf8 Mon Sep 17 00:00:00 2001 From: shriramthebeast Date: Wed, 29 Oct 2025 09:29:21 +0530 Subject: [PATCH 3/5] docs: Updated bulk update script --- .../bulk_update_with_progress.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js index cac9476f32..0ba8d0092e 100644 --- a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js @@ -1,6 +1,3 @@ -// Background Script: Safe Bulk Record Update with Progress Tracking -// Purpose: Update multiple records efficiently using updateMultiple() - var TABLE = 'incident'; // Change to your table var FILTER = "priority=1"; // Add your filter conditions var FIELD_TO_UPDATE = 'state'; // Field to update @@ -8,7 +5,7 @@ var NEW_VALUE = '1'; // Value to set var successCount = 0; var errorCount = 0; - +//using gs.info for best logging gs.info('[Bulk Update Started] Table: ' + TABLE + ' | Filter: ' + FILTER, 'BulkUpdate'); try { @@ -22,19 +19,17 @@ try { recordIds.push(gr.getUniqueValue()); } - // Update all records at once using updateMultiple + //using updateMultiple will update all records at once if (recordIds.length > 0) { var updateGr = new GlideRecord(TABLE); updateGr.addEncodedQuery(FILTER); updateGr.setValue(FIELD_TO_UPDATE, NEW_VALUE); - updateGr.updateMultiple(); - + updateGr.updateMultiple();//this is more efficient successCount = recordIds.length; gs.info('[Bulk Update Complete] Total Updated: ' + successCount, 'BulkUpdate'); } else { gs.info('[Bulk Update] No records matched the filter criteria', 'BulkUpdate'); } - } catch (e) { gs.error('[Bulk Update Error] ' + e.toString(), 'BulkUpdate'); } From d358754e46fd27abdc0ac757cd5e51f7b17a2168 Mon Sep 17 00:00:00 2001 From: Sriram kulkarni <165943146+BEASTSHRIRAM@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:31:00 +0530 Subject: [PATCH 4/5] Clean up README by removing sections Removed example usage, key features, output examples, performance notes, customization, requirements, and related APIs sections from the README. --- .../Safe Bulk Update with Logging/README.md | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md index 9730e4105c..87b5b84c7c 100644 --- a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/README.md @@ -35,60 +35,3 @@ Efficiently update multiple records in batch with error handling, progress track 3. Schedule for off-peak hours 4. Logs will be available in System Logs -## Example Usage -```javascript -// Customize these variables: -var TABLE = 'incident'; -var FILTER = "priority=1^state=2"; // Your query condition -var BATCH_SIZE = 100; -var FIELD_TO_UPDATE = 'assignment_group'; // Field to update -var NEW_VALUE = '123456789abc'; // New value - -// Run the script - it handles everything else -``` - -## Key Features -- **Batch Processing**: Prevents timeout by processing records in chunks -- **Error Resilience**: Continues on error, logs details -- **Progress Tracking**: Logs every N records updated -- **Flexible**: Works with any table and field -- **Safe**: Won't crash on individual record failures -- **Auditable**: Detailed logging of all operations - -## Output Examples -``` -[Bulk Update Started] Processing incidents with filter: priority=1 -[Progress] Updated 100 records successfully (5 errors) -[Progress] Updated 200 records successfully (8 errors) -[Bulk Update Complete] Total: 250 | Success: 242 | Errors: 8 -[Failed Records] 7af24b9c: User already has assignment -[Failed Records] 8bd35c8d: Invalid assignment group -``` - -## Performance Notes -- Batch size of 100 is optimal for most tables -- Adjust batch size based on available resources -- Run during maintenance windows for large updates -- Monitor system logs during execution - -## Customization -```javascript -// Change batch size for your table size -var BATCH_SIZE = 50; // For smaller batches -var BATCH_SIZE = 200; // For larger tables - -// Different field update logic -record.setValue(FIELD_TO_UPDATE, NEW_VALUE); -// Or use gs.getProperty() for configuration -``` - -## Requirements -- ServiceNow instance -- Access to Background Scripts or Scheduled Jobs -- Write access to target table -- Appropriate table and field permissions - -## Related APIs -- [GlideRecord Query API](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_UsingGlideRecord.html) -- [GlideSystem Logging](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_SystemLog.html) -- [Best Practices for Bulk Operations](https://docs.servicenow.com/bundle/sandiego-application-development/page/app-store/dev_apps/concept/c_BulkOperations.html) From 01bd18f6a4fcda92bcff296b7756c21d897b64fe Mon Sep 17 00:00:00 2001 From: Sriram kulkarni <165943146+BEASTSHRIRAM@users.noreply.github.com> Date: Wed, 29 Oct 2025 09:35:05 +0530 Subject: [PATCH 5/5] removed errorcount as it is not being used --- .../Safe Bulk Update with Logging/bulk_update_with_progress.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js index 0ba8d0092e..5bf9a6e5c8 100644 --- a/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js +++ b/Server-Side Components/Background Scripts/Safe Bulk Update with Logging/bulk_update_with_progress.js @@ -4,7 +4,6 @@ var FIELD_TO_UPDATE = 'state'; // Field to update var NEW_VALUE = '1'; // Value to set var successCount = 0; -var errorCount = 0; //using gs.info for best logging gs.info('[Bulk Update Started] Table: ' + TABLE + ' | Filter: ' + FILTER, 'BulkUpdate');