Expired documents cause onDelete to execute twice

I have an eventing function which calls certain apis when a document is deleted via the OnDelete handler. I’m trying to add expiry functionality to documents, however I don’t want to call my apis when a document expires. The issue I’m facing is OnDelete will trigger twice when a document is expired. First, once with options.expired=true which denotes the document is expired, then a second time with options.expired=false. This makes it impossible to prevent my apis from being called due to the second execution of OnDelete. The only solution I can see is creating a separate bucket which gets updated when options.expired=true and is checked when options.expired=false. I’d like to avoid this solution however, as I don’t want to create a new bucket solely for tracking expired documents.

Is there a way I can avoid OnDelete being executed the second time? And if not, is there another solution other than creating a bucket? Thanks in advance.

It sounds like your onDelete() could do processing only when options.expired=true.

What version? What is the definition of your OnDelete() ?

We’re using Couchbase Server Enterprise version 7.1.2. We do have valid flows where documents are deleted without being expired, so we unfortunately can’t solely process on options.expired=true. If OnDelete() only executed once on document expirations this would solve our issue. Is there a way to enforce that outcome? It seems odd OnDelete() fires twice for expired documents.

What is the definition of your OnDelete() ? Does it call delete on the document?

Here’s the definition. We never delete anything in couchbase itself from OnDelete(), we only call apis to perform delete options in a separate database for certain document types. Note, the reason we don’t want these calls happening for expired documents is we only want 18 months worth of data in couchbase, not all historical records. In expiration scenarios, we simply want to document removed from couchbase while persisting in our other database.

function OnDelete(meta, options) {
  const parts = meta.id.split('::');
  if (meta.id.startsWith('_') || parts.length < 2) {
    return;
  }

  if (options.expired) {
    log('DEBUG', { message: 'Document expired', docId: meta.id });
    return;
  }

  // Check if the document is actually deleted
  if (mobile_data[meta.id] !== undefined) {
    return;
  }

  log('DEBUG', { message: 'Document deleted', docId: meta.id });
  const prefix = parts[0];
  const guid = parts[1];

  if (prefix === 'doc_prefix_1') {
    callSomeApi1(guid);
  } else if (prefix === 'doc_prefix_2') {
    callSomeApi2(guid);
  } else if (prefix === 'doc_prefix_3') {
    callSomeApi3(guid);
  }
}

Thanks. Yes - that is what I was wondering. It seems that it should not be called twice. From the documentation, it seems that it should not be called twice.

The OnDelete handler is called when you delete a document or when the document expires.

The entry point OnDelete(meta,options) passes meta, which contains information like the document, and options, which contains the boolean parameter options.expired that indicates if the document was removed because of a deletion or an expiration.

Agreed, I never saw any part of the documentation reference this double execution of OnDelete() behavior. Is this a bug then? If so, is there a known workaround?

I only get one - with expired=true. On 7.1.2 Enterprise.

function OnUpdate(doc, meta, xattrs) {
    log("OnUpdate", meta.id, xattrs);
}

function OnDelete(meta, options) {
    log("OnDelete", meta.id, options);
}

The ‘OnUpdate’ is from a client setting the expiry.

2024-11-05T13:09:58.702-08:00 [INFO] “OnUpdate” “000” undefined
2024-11-05T13:10:24.602-08:00 [INFO] “OnDelete” “000” {“expired”:true}
2024-11-05T13:10:35.303-08:00 [INFO] “OnUpdate” “9b922e51cbe000000000” undefined
2024-11-05T13:10:46.002-08:00 [INFO] “OnDelete” “9b922e51cbe000000000” {“expired”:true}
2024-11-05T13:10:51.203-08:00 [INFO] “OnUpdate” “9b922e51cbe000000001” undefined
2024-11-05T13:11:02.803-08:00 [INFO] “OnDelete” “9b922e51cbe000000001” {“expired”:true}

Interesting. We do have a Sync Gateway instance setup on our bucket, could that play a factor? I know there’s a known issue of double mutations on buckets integrated with Sync Gateway, I didn’t think that’d apply to expirations though.

It seems to be a Sync Gateway induced issue. I tested on a bucket that isn’t connected to Sync Gateway and got the same result as you. Any possible solutions for persisting the normal behavior to buckets associated with Sync Gateway would be greatly appreciated.

From people that know:

Looks like customer is using sync gateway bucket. Sync gateway coexistence is supported in https://jira.issues.couchbase.com/browse/MB-57161 https://jira.issues.couchbase.com/browse/MB-50944 in 7.6.2. This should solve the double mutation issues

1 Like

I believe the access to these Jira tickets are restricted, I’m getting a message saying my email “doesn’t have access to Jira on jira.issues.couchbase.com .”. Is there a different way I can view these? Thanks also for your help and responsiveness!

Not sure about access.
The bottom line is - the issue is fixed in 7.6.2.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.