We're reclaiming inactive PDIs to keep them available for active builders. Learn what's changing, who's affected, and how to protect your work. Read More

Want to clear particular cache by using cache key in business rule

RajeshkumarV
Tera Contributor
Basically, I am trying to override function: getMySubscriptions from script include: ServiceSubscriptionUtilsSNC, because I want to add few more conditions on 
_addGroup function.
 
var SUBSCRIPTIONS_CACHE = 'SUBSCRIPTIONS_CACHE';


        // check the SUBSCRIPTIONS_CACHE if the there is an offering sys_ids array already associated to the user
        var userCachedSubscriptionsArr = sn_scoped_cache.ScopedCacheManager.get(SUBSCRIPTIONS_CACHE, userId);
  if (userCachedSubscriptionsArr)
            return JSON.parse(userCachedSubscriptionsArr);
 
I want to clear this SUBSCRIPTIONS_CACHE cache for particular user from business rule.
Tried the following, but didnt help.
 
Option_1:
var sm = GlideSecurityManager.get();

            sm.setUser(gs.getUser());

 

Option_2:

sn_scoped_cache.ScopedCacheManager.flushScopedCache("SUBSCRIPTIONS_CACHE");

 

Option_3:

var user = gs.getUserID();

sn_scoped_cache.ScopedCacheManager.flushScopedCache("SUBSCRIPTIONS_CACHE", user);

 

 

the only thing working as expected is, full flush: 

gs.cacheFlush();

 

But full flesh is not recommended. Please suggest any other approach. Thanks in advance.

3 REPLIES 3

RajeshkumarV
Tera Contributor

I am still stuck in this issue, could anyone please help here. Thank you.

Pavan Srivastav
ServiceNow Employee

Looking at your problem, the core issue is that sn_scoped_cache.ScopedCacheManager has scoped visibility — the cache written by the ServiceSubscriptionUtilsSNC script include (which runs in the sn_hr_service_portal or similar ServiceNow scope) can only be flushed from within that same scope.

Your Business Rule likely runs in a different scope (global or your custom scope), which is why flushScopedCache silently does nothing.


Root Cause

 
 
javascript
sn_scoped_cache.ScopedCacheManager.get(SUBSCRIPTIONS_CACHE, userId)
// ↑ This cache entry is namespaced to the scope that wrote it
// ↑ Only that same scope can flush it

Recommended Approaches

Option A — Script Include Bridge (Best Practice)

Create a Script Include in the same scope as ServiceSubscriptionUtilsSNC (e.g. sn_hr_service_portal) that exposes a flush method:

 
 
javascript
// Script Include: ServiceSubscriptionCacheUtils
// Scope: sn_hr_service_portal (same scope as ServiceSubscriptionUtilsSNC)
var ServiceSubscriptionCacheUtils = Class.create();
ServiceSubscriptionCacheUtils.prototype = {
    initialize: function() {},

    flushUserCache: function(userId) {
        sn_scoped_cache.ScopedCacheManager.flushScopedCache(
            'SUBSCRIPTIONS_CACHE', 
            userId
        );
    },

    type: 'ServiceSubscriptionCacheUtils'
};

Then call it from your Business Rule:

 
 
javascript
// Business Rule (any scope)
var cacheUtils = new sn_hr_service_portal.ServiceSubscriptionCacheUtils();
cacheUtils.flushUserCache(current.getValue('user')); // pass the user sys_id

This works because the flush executes within the owning scope.


Option B — Scripted REST / Background Script Workaround

If cross-scope Script Includes aren't available to you, trigger a Scripted REST API endpoint defined in the correct scope that performs the flush. Call it via RESTMessageV2 from your Business Rule.


Option C — Override getMySubscriptions to Skip Cache Conditionally

Since you're already overriding getMySubscriptions, you can add a bypass flag on the user session or a temp table, and check it before the cache read:

 
 
javascript
// In your overridden getMySubscriptions
var SUBSCRIPTIONS_CACHE = 'SUBSCRIPTIONS_CACHE';

// Check for bypass flag (e.g. set by your Business Rule via gs.getSession().putClientData)
var bypassCache = gs.getSession().getClientData('bypass_subscription_cache_' + userId);

if (!bypassCache) {
    var userCachedSubscriptionsArr = sn_scoped_cache.ScopedCacheManager.get(
        SUBSCRIPTIONS_CACHE, userId
    );
    if (userCachedSubscriptionsArr)
        return JSON.parse(userCachedSubscriptionsArr);
}

// clear the flag after use
gs.getSession().removeClientData('bypass_subscription_cache_' + userId);

Your Business Rule sets the flag:

 
 
javascript
// Business Rule
gs.getSession().putClientData(
    'bypass_subscription_cache_' + current.getValue('user'), 
    'true'
);

Summary

Option Works Cross-Scope Granular (per user) Recommended
flushScopedCache from BR
gs.cacheFlush() (too broad)
Script Include Bridge
Session bypass flag (if override available)

Option A (Script Include Bridge) is the cleanest and most maintainable — it respects scope boundaries without any workarounds.

RajeshkumarV
Tera Contributor

Option A — Script Include Bridge (Best Practice) - this worked.

But still the catalog items in service portal is not getting refreshed even after nullifying the cache. Still it is showing previous list only.