Button click takes too long / transaction timeout: run the heavy part in the background
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
15m ago
Hi I am happy to share my Lesson Learned Here,
You can achieve this by letting the button (UI Action or GlideAjax) only mark what needs processing and start an On Demand Scheduled Job. The job picks up the marked records and finishes in the background, so the user gets a response in about a second.
Step 1: Create an On Demand Scheduled Job
- Navigate to System Definition → Scheduled Jobs → New → Automatically run a script of your choosing.
- Name: My Reapply Job, Run: On Demand.
- Script:
new MyProcessor().drain();
Step 2: Add a drain() method that only processes marked records
drain: function () { var g = new GlideRecord('u_my_rule'), ids = [], keys = []; g.addQuery('u_review_reason', 'PENDING'); g.query(); while (g.next()) { ids.push(g.getUniqueValue()); keys.push(g.getValue('u_pattern')); } if (!ids.length) return { rows: 0 }; // safe to run any number of times var rows = this._process(keys); // the heavy work var u = new GlideRecord('u_my_rule'); u.addQuery('sys_id', 'IN', ids.join(',')); // clear only what we picked up u.setWorkflow(false); u.query(); u.setValue('u_review_reason', ''); u.updateMultiple(); return { rows: rows }; }Step 3: In the GlideAjax / UI Action, process small requests now and queue large ones
var max = parseInt(gs.getProperty('x.apply_now_max', '20000'), 10); if (affected <= max) { out.rows = this._process(keys); out.mode = 'now'; } else { ids.forEach(function (id) { var g = new GlideRecord('u_my_rule'); if (g.get(id)) { g.setValue('u_review_reason', 'PENDING'); g.setWorkflow(false); g.update(); } }); var job = new GlideRecord('sysauto_script'); if (job.get('name', 'My Reapply Job')) { SncTriggerSynchronizer.executeNow(job); // starts the On Demand job right away out.mode = 'queued'; } else { out.mode = 'batch'; // falls back to the nightly job } } return JSON.stringify(out);Step 4: Show the user what happened
if (o.mode === 'queued') g_form.addInfoMessage('Re-processing started in the background.'); else if (o.mode === 'now') g_form.addInfoMessage(o.rows + ' records updated.');Why the PENDING flag matters: if the job fails or someone deletes it, the flag stays and the next scheduled run still picks the records up. Nothing is lost.
If this helped, please mark it as Helpful
0 REPLIES 0