

Buffy — Buffy v2.0.0

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

[View Source](https://github.com/stordco/buffy/blob/main/README.md#L1 "View Source")

Buffy

=======================================================================================================

Buffy is a small library of Elixir modules to assist in throttling and debouncing function calling.

[Roadmap](#roadmap)

--------------------

* [ ] Allow limiting concurrency of running tasks

* [ ] Create a debounce module

* [X] Telemetry instrumentation

[Installation](#installation)

------------------------------

Just add [`buffy`](https://hex.pm/packages/buffy) to your `mix.exs` file like so:

```

def deps do

 [

 {:buffy, "~> 2.0.0"}

 ]

end

```

[Published Documentation](#published-documentation)

----------------------------------------------------

Documentation is automatically generated and published to [HexDocs](https://hexdocs.pm/buffy/readme.html) on new releases.

[← Previous Page

 

API Reference](api-reference.html)

[Next Page →

 

Changelog](changelog.html)

 document.addEventListener("DOMContentLoaded", function () {

 mermaid.initialize({ startOnLoad: false });

 let id = 0;

 for (const codeEl of document.querySelectorAll("pre code.mermaid")) {

 const preEl = codeEl.parentElement;

 const graphDefinition = codeEl.textContent;

 const graphEl = document.createElement("div");

 const graphId = "mermaid-graph-" + id++;

 mermaid.render(graphId, graphDefinition, function (svgSource, bindListeners) {

 graphEl.innerHTML = svgSource;

 bindListeners && bindListeners(graphEl);

 preEl.insertAdjacentElement("afterend", graphEl);

 preEl.remove();

 });

 }

 });





Buffy — Buffy v2.0.0

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy.ex#L1 "View Source")

Buffy

(Buffy v2.0.0)

=========================================================================================================================

Buffy is broken down into different modules depending on how you want to

handle your function calling.

[Throttle](#module-throttle)

-----------------------------

The [`Buffy.Throttle`](Buffy.Throttle.html) module will wait for a specified amount of time before

invoking the function. If the function is called again before the time has

elapsed, it's a no-op. Once the timer has expired, the function will be called,

and any subsequent calls will start a new timer.

```

call     call   call               call           call

 | call   | call | call             | call         |

 |  |     |  |   |  |               |  |           |

┌─────────┐  ┌─────────┐            ┌─────────┐    ┌─────────┐

│ Timer 1 │  │ Timer 2 │            │ Timer 3 │    │ Timer 4 │

└─────────|  └─────────┘            └─────────┘    └─────────┘

          |            |                      |              |

          |            |                      |    Forth function invocation

          |            |            Third function invocation

          | Second function invocation

First function invocation

```

 document.addEventListener("DOMContentLoaded", function () {

 mermaid.initialize({ startOnLoad: false });

 let id = 0;

 for (const codeEl of document.querySelectorAll("pre code.mermaid")) {

 const preEl = codeEl.parentElement;

 const graphDefinition = codeEl.textContent;

 const graphEl = document.createElement("div");

 const graphId = "mermaid-graph-" + id++;

 mermaid.render(graphId, graphDefinition, function (svgSource, bindListeners) {

 graphEl.innerHTML = svgSource;

 bindListeners && bindListeners(graphEl);

 preEl.insertAdjacentElement("afterend", graphEl);

 preEl.remove();

 });

 }

 });





Buffy.Application — Buffy v2.0.0

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/application.ex#L1 "View Source")

Buffy.Application

(Buffy v2.0.0)

=================================================================================================================================================

The Buffy supervisor responsible for starting the default

[`Registry`](https://hexdocs.pm/elixir/Registry.html) and [`DynamicSupervisor`](https://hexdocs.pm/elixir/DynamicSupervisor.html).

 document.addEventListener("DOMContentLoaded", function () {

 mermaid.initialize({ startOnLoad: false });

 let id = 0;

 for (const codeEl of document.querySelectorAll("pre code.mermaid")) {

 const preEl = codeEl.parentElement;

 const graphDefinition = codeEl.textContent;

 const graphEl = document.createElement("div");

 const graphId = "mermaid-graph-" + id++;

 mermaid.render(graphId, graphDefinition, function (svgSource, bindListeners) {

 graphEl.innerHTML = svgSource;

 bindListeners && bindListeners(graphEl);

 preEl.insertAdjacentElement("afterend", graphEl);

 preEl.remove();

 });

 }

 });





Buffy.Throttle — Buffy v2.0.0

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L1 "View Source")

Buffy.Throttle behaviour

(Buffy v2.0.0)

=====================================================================================================================================================

The [`Buffy.Throttle`](Buffy.Throttle.html#content) module will wait for a specified amount of time before

invoking the function. If the function is called again before the time has

elapsed, it's a no-op. Once the timer has expired, the function will be called,

and any subsequent calls will start a new timer.

```

call     call   call               call           call

 | call   | call | call             | call         |

 |  |     |  |   |  |               |  |           |

┌─────────┐  ┌─────────┐            ┌─────────┐    ┌─────────┐

│ Timer 1 │  │ Timer 2 │            │ Timer 3 │    │ Timer 4 │

└─────────|  └─────────┘            └─────────┘    └─────────┘

          |            |                      |              |

          |            |                      |    Forth function invocation

          |            |            Third function invocation

          | Second function invocation

First function invocation

```

[Example Usage](#module-example-usage)

---------------------------------------

You'll first need to create a module that will be used to throttle.

```

defmodule MyTask do

 use Buffy.Throttle,

 throttle: :timer.minutes(2)

 def handle\_throttle(args) do

 # Do something with args

 end

end

```

Next, you can use the `throttle/1` function with the registered module.

```

iex> MyTask.throttle(args)

:ok

```

[Options](#module-options)

---------------------------

* `:registry_module` (`atom`) - Optional. A module that implements the [`Registry`](https://hexdocs.pm/elixir/Registry.html) behaviour. If you are running in a distributed instance, you can set this value to `Horde.Registry`. Defaults to [`Registry`](https://hexdocs.pm/elixir/Registry.html).

* `:registry_name` (`atom`) - Optional. The name of the registry to use. Defaults to the built in Buffy registry, but if you are running in a distributed instance you can set this value to a named `Horde.Registry` process. Defaults to `Buffy.Registry`.

* `:restart` (`:permanent` | `:temporary` | `:transient`) - Optional. The restart strategy to use for the GenServer. Defaults to `:temporary`.

* `:supervisor_module` (`atom`) - Optional. A module that implements the [`DynamicSupervisor`](https://hexdocs.pm/elixir/DynamicSupervisor.html) behaviour. If you are running in a distributed instance, you can set this value to `Horde.DynamicSupervisor`. Defaults to [`DynamicSupervisor`](https://hexdocs.pm/elixir/DynamicSupervisor.html).

* `:supervisor_name` (`atom`) - Optional. The name of the dynamic supervisor to use. Defaults to the built in Buffy dynamic supervisor, but if you are running in a distributed instance you can set this value to a named `Horde.DynamicSupervisor` process. Defaults to `Buffy.DynamicSupervisor`.

* :throttle (`non_neg_integer`) - Required. The amount of time to wait before invoking the function. This value is in milliseconds.

[Using with Horde](#module-using-with-horde)

---------------------------------------------

If you are running Elixir in a cluster, you can utilize `Horde` to only run one of your throttled functions at a time. To do this, you'll need to set the `:registry_module` and `:supervisor_module` options to `Horde.Registry` and `Horde.DynamicSupervisor` respectively. You'll also need to set the `:registry_name` and `:supervisor_name` options to the name of the Horde registry and dynamic supervisor you want to use.

```

 defmodule MyThrottler do

 use Buffy.Throttle,

 registry\_module: Horde.Registry,

 registry\_name: MyApp.HordeRegistry,

 supervisor\_module: Horde.DynamicSupervisor,

 supervisor\_name: MyApp.HordeDynamicSupervisor,

 throttle: :timer.minutes(2)

 def handle\_throttle(args) do

 # Do something with args

 end

 end

```

[Telemetry](#module-telemetry)

-------------------------------

These are the events that are called by the [`Buffy.Throttle`](Buffy.Throttle.html#content) module:

* `[:buffy, :throttle, :throttle]` - Emitted when the `throttle/1` function is called.

* `[:buffy, :throttle, :handle, :start]` - Emitted at the start of the `handle_throttle/1` function.

* `[:buffy, :throttle, :handle, :stop]` - Emitted at the end of the `handle_throttle/1` function.

* `[:buffy, :throttle, :handle, :exception]` - Emitted when an error is raised in the `handle_throttle/1` function.

All of these events will have the following metadata:

* `:args` - The arguments passed to the `throttle/1` function.

* `:key` - A hash of the passed arguments used to deduplicate the throttled function.

* `:module` - The module using [`Buffy.Throttle`](Buffy.Throttle.html#content).

With the additional metadata for `[:buffy, :throttle, :handle, :stop]`:

* `:result` - The return value of the `handle_throttle/1` function.

[Summary](#summary)

====================

[Types](#types)

----------------

[args()](#t:args/0)

A list of arbitrary arguments that are used for the [`handle_throttle/1`](#c:handle_throttle/1)

function.

[key()](#t:key/0)

A unique key for debouncing. This is used for GenServer uniqueness and is

generated from hashing all of the args.

[state()](#t:state/0)

Internal state that [`Buffy.Throttle`](Buffy.Throttle.html#content) keeps.

[Callbacks](#callbacks)

------------------------

[handle\_throttle(args)](#c:handle_throttle/1)

The function called after the throttle has completed. This function will

receive the arguments passed to the `throttle/1` function.

[throttle(args)](#c:throttle/1)

A function to call the throttle. This will always return a tuple of `{:ok, pid()}`

and wait the configured `throttle` time before calling the [`handle_throttle/1`](#c:handle_throttle/1)

function.

[Types](#types)

================

[Link to this type](#t:args/0 "Link to this type")

args()

======

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L96 "View Source")

```

@type args() :: [term](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()

```

A list of arbitrary arguments that are used for the [`handle_throttle/1`](#c:handle_throttle/1)

function.

[Link to this type](#t:key/0 "Link to this type")

key()

=====

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L102 "View Source")

```

@type key() :: [term](https://hexdocs.pm/elixir/typespecs.html#built-in-types)()

```

A unique key for debouncing. This is used for GenServer uniqueness and is

generated from hashing all of the args.

[Link to this type](#t:state/0 "Link to this type")

state()

=======

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L107 "View Source")

```

@type state() :: {[key](#t:key/0)(), [args](#t:args/0)()}

```

Internal state that [`Buffy.Throttle`](Buffy.Throttle.html#content) keeps.

[Callbacks](#callbacks)

========================

[Link to this callback](#c:handle_throttle/1 "Link to this callback")

handle\_throttle(args)

======================

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L120 "View Source")

```

@callback handle_throttle([args](#t:args/0)()) :: [any](https://hexdocs.pm/elixir/typespecs.html#basic-types)()

```

The function called after the throttle has completed. This function will

receive the arguments passed to the `throttle/1` function.

[Link to this callback](#c:throttle/1 "Link to this callback")

throttle(args)

==============

[View Source](https://github.com/stordco/buffy/blob/main/lib/buffy/throttle.ex#L114 "View Source")

```

@callback throttle(args :: [args](#t:args/0)()) :: {:ok, [pid](https://hexdocs.pm/elixir/typespecs.html#basic-types)()}

```

A function to call the throttle. This will always return a tuple of `{:ok, pid()}`

and wait the configured `throttle` time before calling the [`handle_throttle/1`](#c:handle_throttle/1)

function.

 document.addEventListener("DOMContentLoaded", function () {

 mermaid.initialize({ startOnLoad: false });

 let id = 0;

 for (const codeEl of document.querySelectorAll("pre code.mermaid")) {

 const preEl = codeEl.parentElement;

 const graphDefinition = codeEl.textContent;

 const graphEl = document.createElement("div");

 const graphId = "mermaid-graph-" + id++;

 mermaid.render(graphId, graphDefinition, function (svgSource, bindListeners) {

 graphEl.innerHTML = svgSource;

 bindListeners && bindListeners(graphEl);

 preEl.insertAdjacentElement("afterend", graphEl);

 preEl.remove();

 });

 }

 });

