---
title: Cancel or Overwrite a Timer
description: Demonstrate the functionality for canceling or overwriting an Eventing Timer.
pubDate: 2026-08-17T09:53:44.266Z
antora:
  editUrl: https://github.com/couchbaselabs/docs-devex/edit/release/8.0/modules/eventing/pages/eventing-examples-cancel-overwrite-timer.adoc
  xref: xref:server:eventing:eventing-examples-cancel-overwrite-timer.adoc[]
---

[Consult the llms.txt file for a full list of contents](/llms.txt)
[View original HTML](/server/current/eventing/eventing-examples-cancel-overwrite-timer.html)

# Cancel or Overwrite a Timer

**Goal**: Demonstrate the functionality for canceling or overwriting an Eventing Timer.

**Implementation**: Create a JavaScript function that contains an **OnUpdate** handler and a Timer callback function. The handler listens for mutations or data-changes within a specified source collection. When any document within the this collection is created or modified, the Eventing Function executes a user-defined routine. In this example, we rely on a control document which if mutated controls whether a Timer will be created, canceled, or overwritten.

* **Test 1**: The control document is created or mutated in such a way a Timer is created and fires approximately 60 seconds in the future at which point a document is written to another collection. The original control document, in the source collection is not changed.
* **Test 2**: The control document is mutated in such a way that any existing Timer with the reference of the control document's id (meta.id) is canceled. This has no effect if the Timer created has already fired and executed.
* **Test 3**: The control document is mutated in such a way that any existing Timer with the reference of the control document's id (meta.id) is overwritten. This is equivalent to canceling a timer that already exists, and then creating a new Timer that will fire approximately 60 seconds in the future from the time of being overwritten.

**Preparations**:

For this example, two (2) buckets **'bulk'** and **'rr100'** are required where the latter is intended to be 100% resident. Create the buckets with a minimum size of 100MB. For information on buckets, see [Create a Bucket](../manage/manage-buckets/create-bucket.md). Within the buckets we need three (3) keyspaces **'bulk.data.source'**, **'bulk.data.target'**, and **'rr100.eventing.metadata'**(we loosely follow this [organization](eventing-buckets-to-collections.md#single-tenancy)).

For the Function Scope or RBAC grouping, we will use the **'bulk.data'**, assuming you have the role of either "Full Admin" or "Eventing Full Admin". For standard or non-privileged users refer to [Eventing Role-Based Access Control](eventing-rbac.md).

_If you run a version of Couchbase prior to 7.0 you can just create the buckets **'source'**, **'target'**, and **'metadata'** and run this example. Furthermore if your cluster was subsequently upgraded from say 6.6.2 to 7.0 your data would be moved to **'source.\_default.\_default'**, **'target.\_default.\_default'**, and **'metadata.\_default.\_default'** and your Eventing Function would be seamlessly upgraded to use the new keyspaces and continue to run correctly._

For complete details on how to set up your keyspaces refer to [creating buckets](../manage/manage-buckets/create-bucket.md) and [creating scopes and collections](../manage/manage-scopes-and-collections/manage-scopes-and-collections.md).

> [!NOTE]
> The Eventing Storage keyspace, in this case **'rr100.eventing.metadata'**, is for the sole use of the Eventing system, do not add, modify, or delete documents from it. In addition do not drop or flush or delete the containing bucket (or delete this collection) while you have any deployed Eventing functions. In a single tenancy deployment this collection can be shared with other Eventing functions.

**Setup**:

1. Access the **Couchbase Web Console** \> **Buckets** page.

  * You should see the following once you have created your buckets:  
  ![cancel overwrite timer 01 buckets](_images/cancel_overwrite_timer_01_buckets.png)
2. \[Optional Step\] Verify we have our empty collections:

  * Click the **Scopes & Collections** link of the **bulk** bucket (on the right).
  * Click the **data** scope name to expand the section (on the left).
  * You should see no user records.  
  ![cancel overwrite timer 01 data in scope](_images/cancel_overwrite_timer_01_data_in_scope.png)
3. Click the **Documents** link of the **source** collection (on the right).

  * Again you should see no user records.  
  ![cancel overwrite timer 01 documents](_images/cancel_overwrite_timer_01_documents.png)
  * Click **Add Document** in the upper right banner
  * For the **ID** in the **Create New Document** dialog specify **type\_of\_interest::1**  
  ID [ type_of_interest::1 ]         ]
  * For the document body in the **Create New Document** dialog, the following text is displayed:  
  {  
  "click": "to edit",  
  "with JSON": "there are no reserved field names"  
  }
  * replace the above text with the following JSON document via a cut-n-paste  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": false,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 1  
  }  
  ![cancel overwrite timer 01 docdata](_images/cancel_overwrite_timer_01_docdata.png)
  * Click **Save**.
4. From the **Couchbase Web Console** \> **Eventing** page, click **ADD FUNCTION**, to add a new Function. The **ADD FUNCTION** dialog appears.
5. In the **ADD FUNCTION** dialog, for individual Function elements provide the below information:

  * For the **Function Scope** drop-down, select **'bulk.data'** as the RBAC grouping.
  * For the **Listen To Location** drop-down, select **bulk**, **data**, **source** as the keyspace.
  * For the **Eventing Storage** drop-down, select **rr100**, **eventing**, **metadata** as the keyspace.
  * Enter **cancel\_overwrite\_timer** as the name of the Function you are creating in the **Function Name** text-box.
  * Leave the "Deployment Feed Boundary" as Everything.
  * \[Optional Step\] Enter text **Explore creating, canceling, and overwriting timers**, in the **Description** text-box.
  * For the **Settings** option, use the default values.
  * For the **Bindings** option, add just one binding.

    * For the first binding, select "bucket alias", specify **tgt\_col** as the "alias name" of the collection, select **bulk**, **data**, **target** as the associated keyspace, and select "read and write" for the access mode.
  * After configuring your settings the **ADD FUNCTION** dialog should look like this:  
  ![cancel overwrite timer 01 settings](_images/cancel_overwrite_timer_01_settings.png)
6. After providing all the required information in the **ADD FUNCTION** dialog, click **Next: Add Code**. The **cancel\_overwrite\_timer** dialog appears.

  * The **cancel\_overwrite\_timer** dialog initially contains a placeholder code block. You will substitute your actual **cancel\_overwrite\_timer** code in this block.  
  ![cancel overwrite timer 02 editor with default](_images/cancel_overwrite_timer_02_editor_with_default.png)
  * Copy the following Function, and paste it in the placeholder code block of **cancel\_overwrite\_timer** dialog.  
  ```javascript  
  function DocTimerCallback(context) {  
     log('From DocTimerCallback: timer fired', context);  
     // Create a new document as per our received context in another collection  
     tgt_col[context.docId] = context; // upsert the context as our new doc  
  }  
  function OnUpdate(doc,meta) {  
     // You would typically filter to mutations of interest  
     if (doc.type != 'type_of_interest') return;  
     // You would typically look at some key conditions to decide what to do  
     if (doc.needed_condition === true && doc.cancel_timer === false) {  
         if (doc.overwrite_timer === true) {  
           log('From OnUpdate: overwriting timer with same reference', meta.id);  
         } else {  
           log('From OnUpdate: creating timer', meta.id);  
         }  
         // Create a timestamp 60 seconds from now  
         var oneMinuteFromNow = new Date(); // Get current time & add 60 sec. to it.  
         oneMinuteFromNow.setSeconds(oneMinuteFromNow.getSeconds() + 60);  
         // Create a document to use as out for our context  
         var context = {docId : meta.id, random_text : "arbitrary text", "tmr_time_to_fire": oneMinuteFromNow};  
         createTimer(DocTimerCallback, oneMinuteFromNow, meta.id, context);  
      }  
      if (doc.cancel_timer === true && doc.overwrite_timer === false) {  
         // Cancel an existing timer (if it is active) by reference meta.id  
         if (cancelTimer(DocTimerCallback, meta.id)) {  
             log('From OnUpdate: cancel request, timer was canceled',meta.id);  
         } else {  
             log('From OnUpdate: cancel request, no such timer may have fired',meta.id);  
         }  
      }  
      if (doc.cancel_timer === true && doc.overwrite_timer === true) {  
          log('From OnUpdate: both cancel and overwrite, will ignore',meta.id);  
      }  
  }  
  ```  
  After pasting, the screen appears as displayed below:  
  ![cancel overwrite timer 03 editor with code](_images/cancel_overwrite_timer_03_editor_with_code.png)
  * Click **Save and Return**.
7. The **OnUpdate** routine specifies that when a change occurs to data within the source collection, actions will be processed according to the field within the document. First we ignore all documents that do not have a doc.type of "type\_of\_interest" this is the control document. Next we use the field as "needed\_condition", "cancel\_timer", and "overwrite\_timer" to determine which action we take.

  * If "needed\_condition" is true and both "cancel\_timer", and "overwrite\_timer" are false we will create a Timer that will fire approximately 60 seconds in the future.
  * If "needed\_condition" is true and "cancel\_timer" is true we will cancel the existing Timer.
  * If "needed\_condition" is true and "overwrite\_timer" is true we will overwrite the existing Timer with a new one (assuming that our Timer is still active) which will fire approximately 60 seconds in the future.
  * If both "cancel\_timer" and "overwrite\_timer" are true it is considered an error and no action is taken.
  * In the event a Timer created by this Function fires the callback **DocTimerCallback** executes and will write a new document with the same KEY (as the "source" collection) into the "target" collection.
8. From the **Eventing** screen, click the **cancel\_overwrite\_timer** function to select it, then click **Deploy**.  
![cancel overwrite timer 03a deploy](_images/cancel_overwrite_timer_03a_deploy.png)  

  * In the **Confirm Deploy Function** Click **Deploy Function**.
9. The Eventing function is deployed and starts running within a few seconds. From this point, the defined Function is executed on all existing documents and will also more importantly it will also run on subsequent mutations.

## [](#test-1-create-a-timer-and-allow-the-timer-to-fire)Test 1: Create a Timer and allow the Timer to Fire

1. Access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`source`

  * Edit the control document type\_of\_interest::1 — it should look like:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": false,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 1  
  }  
  Change "needed\_condition" to true to create a mutation, then click **Save**. This will create a mutation and then the Function will generate a Timer. The control document is now:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 1  
  }
2. Access the **Couchbase Web Console** \> **Eventing** page and click on the Function **cancel\_overwrite\_timer** then click the "Log" link for Deployed Function **cancel\_overwrite\_timer** to view the activity.

  * Here we see from the Application log that we created a timer.  
  2022-05-10T16:06:54.226-07:00 [INFO] "From OnUpdate: creating timer" "type_of_interest::1 "  
  ![cancel overwrite timer 04 log active1](_images/cancel_overwrite_timer_04_log_active1.png)
3. Close the Function Log dialog, then wait about 80 seconds and click the "Log" link for the Deployed Function **cancel\_overwrite\_timer** to view the activity again.

  * Here we see the timer fired and executed the callback **DocTimerCallback** near our scheduled time.  
  2022-05-10T16:08:01.804-07:00 [INFO] "From DocTimerCallback: timer fired" {"docId":"type_of_interest::1 ","random_text":"arbitrary text","tmr_time_to_fire":"2022-05-10T23:07:54.226Z"}  
  ![cancel overwrite timer 04 log fired1](_images/cancel_overwrite_timer_04_log_fired1.png)
4. Now, to check the results of the callback, access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`target`

  * You should see one newly created document in the collection "target".  
  ![cancel overwrite timer 04 look target](_images/cancel_overwrite_timer_04_look_target.png)
  * Edit the new document type\_of\_interest::1 and you will see the data written by the Timer's callback:  
  {  
    "docId": "type_of_interest::1",  
    "random_text": "arbitrary text",  
    "tmr_time_to_fire": "2022-05-10T23:07:54.226Z"  
  }
  * Click **Cancel** to close the editor.
5. Click the trash can icon to delete the document, then click **Continue** to confirm the deletion.

## [](#test-2-create-a-timer-then-cancel-the-timer)Test 2: Create a Timer then Cancel the Timer:

1. Access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`source`

  * Edit the control document **type\_of\_interest::1** — it should look like this:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 1  
  }  
  Change "a\_number" to 2 to create a mutation, then click **Save**. The control document is now:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 2  
  }
2. Access the **Couchbase Web Console** \> **Eventing** page and if necessary select the Function **cancel\_overwrite\_timer**, then click the "Log" link for Deployed Function to view the activity.

  * Here we see from the Application log that we once again created a timer.  
  2022-05-10T16:10:14.326-07:00 [INFO] "From OnUpdate: creating timer" "type_of_interest::1 "
3. Access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`source`

  * Edit the control document **type\_of\_interest::1** — it should look like this:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 2  
  }  
  Change "cancel\_timer" to true to create a mutation, then click **Save**. The control document is now:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": true,  
    "overwrite_timer": false,  
    "a_number": 2  
  }
4. Access the **Couchbase Web Console** \> **Eventing** page and if necessary select the Function **cancel\_overwrite\_timer**, then click the "Log" link for Deployed Function to view the activity.

  * Here we see from the Application log the timer was canceled and will never fire.  
  2022-05-10T16:11:21.429-07:00 [INFO] "From OnUpdate: cancel request, timer was canceled" "type_of_interest::1 "

## [](#test-3-create-a-timer-then-overwrite-the-timer)Test 3: Create a Timer then Overwrite the Timer

1. Access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`source`

  * Edit the control document **type\_of\_interest::1** — it should look like this:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": true,  
    "overwrite_timer": false,  
    "a_number": 2  
  }  
  Change "cancel\_timer" to false to create a mutation, then click **Save**. This will create a mutation and then the Function will generate a Timer. The control document is now:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 2  
  }
2. Access the **Couchbase Web Console** \> **Eventing** page and if necessary select the Function **cancel\_overwrite\_timer**, then click the "Log" link for Deployed Function to view the activity.

  * Here we see from the Application log that we created a timer.  
  2022-05-10T16:12:07.126-07:00 [INFO] "From OnUpdate: creating timer" "type_of_interest::1 "
3. Access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`source`

  * Edit the control document **type\_of\_interest::1** — it should look like this:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": false,  
    "a_number": 2  
  }  
  Change "overwrite\_timer" to true to create a mutation, then click **Save**. The control document is now:  
  {  
    "type": "type_of_interest",  
    "id": 1,  
    "needed_condition": true,  
    "cancel_timer": false,  
    "overwrite_timer": true,  
    "a_number": 2  
  }
4. Access the **Couchbase Web Console** \> **Eventing** page and if necessary select the Function **cancel\_overwrite\_timer**, then click the "Log" link for Deployed Function to view the activity.

  * Here we see from the Application log the timer was overwritten and will fire at a later time.  
  2022-05-10T16:12:57.125-07:00 [INFO] "From OnUpdate: overwriting timer with same reference" "type_of_interest::1 "
5. \[Optional\] mutate the document several times by changing "a\_number" — this will overwrite the timer multiple times.
6. Wait about 80 seconds and click the "Log" link for Deployed Function **cancel\_overwrite\_timer** to view the activity.

  * Here we see the timer fired and executed the callback **DocTimerCallback** near our scheduled time.  
  2022-05-10T16:14:05.811-07:00 [INFO] "From DocTimerCallback: timer fired" {"docId":"type_of_interest::1 ","random_text":"arbitrary text","tmr_time_to_fire":"2022-05-10T23:13:57.125Z"}
7. Now, to check the results of the callback, access the **Couchbase Web Console** \> **Documents** page then select the keyspace `bulk`.`data`.`target`

  * Edit the new document **type\_of\_interest::1** and you will see the data written by the Timer's callback:  
  {  
    "docId": "type_of_interest::1 ",  
    "random_text": "arbitrary text",  
    "tmr_time_to_fire": "2022-05-10T23:13:57.125Z"  
  }
  * Click **Cancel** to close the editor.
8. Click the trash can icon to delete the document, then click **Continue** to confirm the deletion.

**Cleanup**:

Go to the Eventing portion of the UI and undeploy the Function **cancel\_overwrite\_timer**, this will remove the 1280 documents (2048 prior to 7.0.0) for the function from the 'rr100.eventing.metadata' collection (in the Bucket view of the UI). Remember you may only delete the 'rr100.eventing.metadata' keyspace if there are no deployed Eventing Functions.

Now flush the 'bulk' bucket if you plan to run other examples (you may need to Edit the bucket 'bulk' and enable the flush capability).