---
schema_version: "1"
id: bb90fe33ca5d2b8b4f5aa2a0285d609e547ef321759dd4393fbf2a41c329f9cd
title: Configuring Delayed, Periodic, and Synchronous Functions
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/pdk/1.8/policies-pdk-configure-features-timer.md
canonical_url: https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-timer
source_site: docs.mulesoft.com
content_type: documentation
content_hash: fdef17b6ab7a6f0231c583908e46805e825549656fd5927ea291be4ee2b9793c
description: MuleSoft Documentation Site
release: "1.8"
latest: false
---
---
product: Omni Gateway Policy Development Kit (PDK)
version: 1.8
---

# Configuring Delayed, Periodic, and Synchronous Functions

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

Use the `Clock` injectable to build a timer to enable delayed, periodic, and synchronous functions.
Each policy supports only one timer.

Each timer provides the following async methods:

```rust
pub async fn next_tick(&self) -> bool;
pub async fn sleep(&self, interval: Duration) -> bool;
pub fn now(&self) -> bool;
```

- `next_tick`: Sleeps for the minimum amount of time the timer is capable of distinguishing.

- `sleep`: Sleeps for an amount of ticks where the elapsed time is greater or equal than the
  provided `Duration`. For example, if you configure the period of the clock to 10 seconds, calling
  `timer.sleep(Duration::from_secs(1))` sleeps for 10 seconds.

- `now`: Returns the current date and time.

Both functions return `true` when the specified time has passed or `false` if the policy is
unapplied or edited during execution.

## Configure the Timer

To inject a timer in your policy, insert a `Clock` into your policy configuration function and
define a timer with a time period:

```rust
#[entrypoint]
async fn configure(
   launcher: Launcher,
   Configuration(bytes): Configuration,
   clock: Clock, // Inject the clock to be able to launch async tasks.
   client: HttpClient,
) -> Result<()> {


   // set the period between ticks of the timer.
   let timer = clock.period(Duration::from_secs(10));
```

After you inject the timer, share a its reference with the `on_request` and `on_response` functions
to begin creating delayed functions:

```rust
    launcher
        .launch(on_request(|rs| request_filter(rs, &timer, &config)))
        .await?;
```

You can now await timer functions in `on_request` and `on_response` functions, for example:

- Use the `.sleep` or `.next_tick` function:

  ```rust
      let slept = timer.sleep(duration).await;
      let tick = timer.next_tick().await;
  ```

- Use the `.now` function:

  ```rust
  async fn filter(
      state: RequestState,
      timer: &Timer,
  ) {
      let state = state.into_headers_state().await;
      let now: chrono::DateTime<chrono::Utc> = timer.now().into();
      state.handler().set_header("Date", now.format("%a, %d %b %Y %H:%M:%S GMT").to_string().as_str());
  }
  ```

> [!NOTE] To view an example policy project that launches delayed functions, see
> [Spike Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/spike/README.md).

## Release the Clock

To create a new timer with a different tick period, release the `Clock` by using the following
method:

```rust
pub fn release(self) -> Clock;
```

The following code snippet creates a timer and then releases the clock to create a new timer:

```rust
    // Configure an initial tick period.
    let initial_timer = clock.period(Duration::from_millis(500));
    some_initial_task(&other_timer).await;
    // Configure another tick period.
    let other_timer = initial_timer.release().period(Duration::from_millis(3000);
    some_other_task(&other_timer).await;
    // Get the clock back.
    let clock = other_timer.release();
```

## Launch Asynchronous Tasks

Use the timer to execute tasks independent of the request flow. To execute asynchronous tasks:

1.  Define your task inside an `async` function.

2.  In the policy configuration function, call your function but don’t await the returned future.

3.  In the policy configuration function, call the `launch` function with the `on_request` and
    `on_response` filter functions but don’t await the returned future.

4.  Use the `join!` macro to await both futures of your task function and `launch` function at the
    same time.

    > [!NOTE] To use the `join` macro, add the ‘futures’ crate as dependency in your `cargo.toml`
    > file.

Each worker executes a copy of the task. Configure a loop inside the function to execute periodic
tasks. For example, the following code example awaits both functions:

```rust
let task = my_async_task(&timer, &config);
let launched = launcher.launch(filter);
let joined = join!(launched, task);
```

Adding a loop to the `my_async_task` function creates periodic tasks, for example:

```rust
async fn my_async_task(timer: &Timer, config: &Config) {
    // While the policy is still running.
    // Wait for the next cycle.
    while timer.next_tick().await {
        // Execute periodic task
    }
}
```

To launch multiple asynchronous tasks, send a reference of the timer to your `async` functions and
join them with the `launch` task, for example:

```rust
let task1 = my_async_task1(&timer, &config);
let task2 = my_async_task2(&timer, &config);
let launched = launcher.launch(filter);
let joined = join!(launched, task1, task2);
```

> [!NOTE] To view an example policy project that launches asynchronous periodic tasks, see
> [Metrics Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/metrics/README.md).

## Sync Asynchronous Tasks between Workers

Use the PDK `LockBuilder` to sync workers. The lock ensures that only one worker is completing a
task in a time period. Each policy supports multiple locks.

Locks are useful when a policy consumes an HTTP service that has usage limits. A single worker can
fetch data and then share the data with other workers to reduce service requests.

To configure a lock:

1.  Inject the `LockBuilder` into your policy configuration function:

    ```rust
    #[entrypoint]
    async fn configure(
        launcher: Launcher,
        Configuration(bytes): Configuration,
        clock: Clock,        // Inject the clock to be able to launch async tasks.
        lock: LockBuilder,   // Inject the lock to be able to synchronize the workers.
    ) -> Result<()> {
    ```

2.  Configure the lock and share a reference of it with your asynchronous function:

    ```rust
        let lock = lock
            .new(ID.to_string())
            .expiration(Duration::from_secs(20))
            .build();
        let task = my_async_task(&timer, &lock);
    ```

    If the asynchronous task executes additional `async` function calls inside the task, configure
    the `expiration` of the lock to a duration longer than the total time needed to complete the
    nested `async` function calls.

3.  Inside the asynchronous function, acquire the lock before executing the desired task. If no
    other worker has the lock, the current worker acquires the lock. Otherwise, you must omit the
    execution of the task and wait for the next task loop, for example:

    ```rust
    async fn my_async_task(
        timer: &Timer,
        lock: &TryLock,
    ) {
       while timer.next_tick().await {
         if let Some(acquired) = lock.try_lock() {
           // execute task.
         }
       }
    }
    ```

    After obtaining the lock, if you execute code that requires you await a result, you must call
    the `refresh_lock` function to ensure the lock hasn’t expired. If the lock has expired, the
    worker is considered unresponsive. Abort the execution of your task because another worker is
    running the same task execution.

> [!NOTE] To view an example policy project that synchronizes asynchronous periodic tasks and shares
> information between workers, see
> [Block Policy Example](https://github.com/mulesoft/pdk-custom-policy-examples/blob/1.8.0/block/README.md).

## See Also

- [Injecting Parameters](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-inject-parameters)

- [Rate Limiting Requests](https://docs.mulesoft.com/pdk/1.8/policies-pdk-configure-features-rate-limiting)
