How to Receive Only the Last Update from Asana Task Updated In Project Source Trigger Instead of Multiple Updates?

This topic was automatically generated from Slack. You can find the original thread here.

, the Asana Task Updated In Project (Instant) source trigger is very noisy. It sends a new event as I’m typing the task name and description, almost at every new character typed. How can I receive only the last update, and not a series of updates?

To address the issue of receiving too many events from the Asana Task Updated In Project (Instant) trigger as you type, you can implement a delay mechanism in your Pipedream workflow to wait for a certain period of time before processing the event. This way, you can ensure that only the last update is processed if multiple updates are received in a short period. Here’s a general approach to achieve this: 1. Use a Data Store to Save the Last Event Timestamp: When an event is received, store the current timestamp in a Pipedream Data Store. This will be used to determine if enough time has passed since the last update. 2. Implement a Delay: After storing the timestamp, implement a delay in your workflow. This delay should be long enough to allow a user to finish typing without triggering multiple events. For example, a delay of a few seconds might be sufficient. 3. Check the Timestamp After the Delay: After the delay, check the timestamp stored in the Data Store. If the current time is within a certain threshold of the stored timestamp (indicating that no new updates have been received during the delay), proceed with processing the event. Otherwise, ignore the event. Here’s an example of how you might implement this logic in a Pipedream workflow step using Node.js: import { axios } from "@pipedream/platform" export default defineComponent({ props: { data: { type: "data_store" }, }, async run({ steps, $ }) { const lastUpdateTimestamp = await this.data.get('lastUpdateTimestamp'); const currentTimestamp = new Date().getTime(); // If this is the first event or if enough time has passed since the last update if (!lastUpdateTimestamp || currentTimestamp - lastUpdateTimestamp > 5000) { // Process the event here // Then update the last update timestamp in the Data Store await this.data.set('lastUpdateTimestamp', currentTimestamp); } else { // If not enough time has passed, ignore the event console.log("Ignoring the event as it's too close to the previous one."); } }, }) This example checks if more than 5 seconds have passed since the last update before processing the event. Adjust the time threshold (5000 milliseconds in this example) as needed based on your specific requirements. Remember, this approach introduces a delay in processing events, so you

yes I already created a debounce function using the same concepts.

export default defineComponent({
  name: "Event Debounce",
  key: "event-debounce",
  version: "0.0.1",
  type: "action",
  props: {
    triggerContext: {
      type: "string",
      // label: "trigger_context",
    },
    dataStore: {
      type: "data_store",
    },
  },
  
  async run({ $ }) {
    console.log({triggerContext: this.triggerContext})
    const emitter_id = this.triggerContext.emitter_id
    const workflow_id = this.triggerContext.workflow_id
    const ts = this.triggerContext.ts

    const emitter_ids = await this.dataStore.get(`emitter_ids`) || {}
    const workflow_ids = await this.dataStore.get(`workflow_ids`) || {}

    let emitterRecord = emitter_ids[emitter_id] || null
    let workflowRecord = workflow_ids[workflow_id] || null

    if (!emitterRecord) {
      emitter_ids[emitter_id] = { workflow_id, ts }
      await this.dataStore.set('emitter_ids', emitter_ids)
    }

    if (!workflowRecord) {
      workflow_ids[workflow_id] = { emitter_id, ts }
      await this.dataStore.set('workflow_ids', workflow_ids)
    }

    const triggerDate = new Date(ts)
    const workflowRecordDate = new Date(workflow_ids[workflow_id].ts)
    const emitterRecordDate = new Date(emitter_ids[emitter_id].ts)
    const thresholdTime = 1 ** 1 ** 1 ** 15 ** 1000 // 15 seconds

    console.log({ 
      emitter_id, 
      emitter_ids, 
      workflow_id, 
      workflow_ids, 
      triggerDate, 
      workflowRecordDate, 
      emitterRecordDate 
    })

    const timeDifference = triggerDate - workflowRecordDate
    const exceedsThreshold = timeDifference > thresholdTime

    console.log({timeDifference})
    
    if (!timeDifference) {
      // This block might be useful for handling scenarios when the record was just created.
      console.log('New record created')

    } else {
      // Check if trigger event is too recent
      if (!exceedsThreshold) {
        // too new, exit flow
        $.flow.exit('Record too recent, exiting flow')

      } else {
        // enough time has passed, proceed
        
        // Update emitterRecord if it exists and time exceeded threshold
        if (emitterRecord && (triggerDate - new Date(emitterRecord.ts)) > thresholdTime) {
          emitter_ids[emitter_id] = { workflow_id, ts };
          emitterRecord = emitter_ids[emitter_id];
          await this.dataStore.set('emitter_ids', emitter_ids);
          console.log('Updated emitterRecord with the latest record');
        }

        // Update workflowRecord if it exists and time exceeded threshold
        if (workflowRecord && (triggerDate - new Date(workflowRecord.ts)) > thresholdTime) {
          workflow_ids[workflow_id] = { emitter_id, ts };
          workflowRecord = workflow_ids[workflow_id];
          await this.dataStore.set('workflow_ids', workflow_ids);
          console.log('Updated workflowRecord with the latest record');
        }
      }
    }
    
    console.log({
      emitter_id,
      emitter_ids,
      workflow_id,
      workflow_ids,
      triggerDate,
      workflowRecordDate: new Date(workflow_ids[workflow_id]?.ts),
      workflowRecord,
      emitterRecordDate: new Date(emitter_ids[emitter_id]?.ts),
      emitterRecord,
    })

  },
})

I was hoping there was another way, something built-in

It looks like you’ve implemented a custom debounce function using Pipedream’s data stores to manage event timing and prevent actions from being triggered too frequently. This is a creative solution, and Pipedream’s flexibility allows for such custom implementations. However, regarding your question about a built-in solution for debouncing events directly within Pipedream, as of my last update, Pipedream does not offer a built-in “debounce” feature as part of its workflow actions or triggers. The platform provides a variety of tools for managing and manipulating workflow execution, such as the Delay action (Delay documentation) and the ability to programmatically control the flow of execution using code steps. However, these tools serve different purposes and do not directly implement debouncing logic. Your approach of using data stores to track event timestamps and manage execution based on time differences is a valid way to implement debouncing logic within Pipedream workflows. It gives you the flexibility to define custom thresholds and conditions for your specific use case. If you’re looking for more streamlined or different approaches, you might consider: 1. External Debouncing Services: Using an external service or API that provides debouncing functionality and integrating it with your Pipedream workflow. 2. Feedback to Pipedream: Since Pipedream is continually evolving, you can suggest new features or enhancements through their community forum or directly via support. A built-in debounce action or trigger enhancement could be valuable to many users. For now, your custom implementation is a solid approach, and leveraging Pipedream’s data stores for this purpose is both creative and effective. If you have any further questions or need assistance optimizing your solution, feel free to reach out to Pipedream’s support at Support - Pipedream.