

API Reference — wait\_for\_it v1.3.0

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

wait\_for\_it v1.3.0

 API Reference

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

 Modules

----------

[WaitForIt](WaitForIt.html)

WaitForIt provides macros for various ways to wait for things to happen.

[WaitForIt.ConditionVariable](WaitForIt.ConditionVariable.html)





WaitForIt — wait\_for\_it v1.3.0

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

wait\_for\_it v1.3.0

WaitForIt [View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it.ex#L1 "View Source")

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

WaitForIt provides macros for various ways to wait for things to happen.

Since most Elixir systems are highly concurrent there must be a way to coordinate and synchronize

the processes in the system. While the language provides features (such as [`Process.sleep/1`](https://hexdocs.pm/elixir/Process.html#sleep/1) and

`receive`/`after`) that can be used to implement such synchronization, they are inconvenient to

use for this purpose. [`WaitForIt`](#content) builds on top of these language features to provide convenient

and easy-to-use facilities for synchronizing concurrent activities. While this is likely most

useful for test code in which tests must wait for concurrent or asynchronous activities to

complete, it is also useful in any scenario where concurrent processes must coordinate their

activity. Examples include asynchronous event handling, producer-consumer processes, and

time-based activity.

There are three distinct forms of waiting provided:

1. The `wait` macro waits until a given expression evaluates to a truthy value.

2. The `case_wait` macro waits until a given expression evaluates to a value that

matches any one of the given case clauses (looks like an Elixir `case` expression).

3. The `cond_wait` macro waits until any one of the given expressions evaluates to a truthy

value (looks like an Elixir `cond` expression).

All three forms accept the same set of options to control their behavior:

* `:timeout` - the amount of time to wait (in milliseconds) before giving up

* `:frequency` - the polling frequency (in milliseconds) at which to re-evaluate conditions

* `:signal` - disable polling and use a condition variable of the given name instead

* `:pre_wait` - wait for the given number of milliseconds before evaluating conditions for the first time

The `:signal` option warrants further explanation. By default, all three forms of waiting use

polling to periodically re-evaluate conditions to determine if waiting should continue. The

frequency of polling is controlled by the `:frequency` option. However, if the `:signal` option

is given it disables polling altogether. Instead of periodically re-evaluating conditions at a

particular frequency, a *condition variable* is used to signal when conditions should be

re-evaluated. It is expected that the `signal` macro will be used to unblock the waiting code

in order to re-evaluate conditions. For example, imagine a typical producer-consumer problem in

which a consumer process waits for items to appear in some buffer while a separate producer

process occasionally place items in the buffer. In this scenario, the consumer process might use

the `wait` macro with the `:signal` option to wait until there are some items in the buffer and

the producer process would use the `signal` macro to tell the consumer that it might be time for

it to check the buffer again.

```

# CONSUMER

# assume the existence of a `buffer\_size` function

WaitForIt.wait buffer\_size() >= 4, signal: :wait\_for\_buffer

```

```

# PRODUCER

# put some things in buffer, then:

WaitForIt.signal(:wait\_for\_buffer)

```

Notice that the same condition variable name `:wait_for_buffer` is used in both cases. It is

important to note that when using condition variables for signaling like this, both the `wait`

invocation and the `signal` invocation should be in the same Elixir module. This is because

[`WaitForIt`](#content) uses the calling module as a namespace for condition variable names to prevent

accidental name collisions with other registered processes in the application. Also note that

just because a condition variable has been signalled does not necessarily mean that any waiters

on that condition variable can stop waiting. Rather, a signal indicates that waiters should

re-evaluate their waiting conditions to determine if they should continue to wait or not.

[Link to this section](#summary)

 Summary

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

[Functions](#functions)

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

[case\_wait(expression, opts \\ [], blocks)](#case_wait/3)

Wait until the given `expression` matches one of the case clauses in the given block.

[cond\_wait(opts \\ [], blocks)](#cond_wait/2)

Wait until one of the expressions in the given block evaluates to a truthy value.

[signal(condition\_var)](#signal/1)

Send a signal to the given condition variable to indicate that any processes waiting on the

condition variable should re-evaluate their wait conditions.

[wait(expression, opts \\ [])](#wait/2)

Wait until the given `expression` evaluates to a truthy value.

[Link to this section](#functions)

Functions

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

[Link to this macro](#case_wait/3 "Link to this macro")

case\_wait(expression, opts \\ [], blocks)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it.ex#L181 "View Source")

(macro)

Wait until the given `expression` matches one of the case clauses in the given block.

Returns the value of the matching clause, the value of the optional `else` clause,

or a tuple of the form `{:timeout, timeout_milliseconds}`.

The `do` block passed to this macro must be a series of case clauses exactly like a built-in

Elixir `case` expression. Just like a `case` expression, the clauses will attempt to be matched

from top to bottom and the first one that matches will provide the resulting value of the

expression. The difference with `case_wait` is that if none of the clauses initially matches it

will wait and periodically re-evaluate the clauses until one of them does match or a timeout

occurs.

An optional `else` clause may also be used to provide the value in case of a timeout. If an

`else` clause is provided and a timeout occurs, then the `else` clause will be evaluated and

the resulting value of the `else` clause becomes the value of the `case_wait` expression. If no

`else` clause is provided and a timeout occurs, then the value of the `case_wait` expression is a

tuple of the form `{:timeout, timeout_milliseconds}`.

The optional `else` clause may also take the form of match clauses, such as those in a case

expression. In this form, the `else` clause can match on the final value of the expression that

was evaluated before the timeout occurred. See the examples below for an example of this.

 Options

----------

See the WaitForIt module documentation for further discussion of these options.

* `:timeout` - the amount of time to wait (in milliseconds) before giving up

* `:frequency` - the polling frequency (in milliseconds) at which to re-evaluate conditions

* `:signal` - disable polling and use a condition variable of the given name instead

* `:pre_wait` - wait for the given number of milliseconds before evaluating conditions for the first time

 Examples

-----------

 Wait until queue has at least 5 messages, then return them:

```

WaitForIt.case\_wait Queue.get\_messages(queue), timeout: 30\_000, frequency: 100 do

 messages when length(messages) > 4 -> messages

else

 # If after 30 seconds we still don't have 5 messages, just return the messages we do have.

 messages -> messages

end

```

 A thermostat that keeps temperature in a small range:

```

def thermostat(desired\_temperature) do

 WaitForIt.case\_wait get\_current\_temperature() do

 temp when temp > desired\_temperature + 2 ->

 turn\_on\_air\_conditioning()

 temp when temp < desired\_temperature - 2 ->

 turn\_on\_heat()

 end

 thermostat(desired\_temperature)

end

```

 Ring the church bells every 15 minutes:

```

def church\_bell\_chimes do

 count = WaitForIt.case\_wait Time.utc\_now.minute, frequency: 60\_000, timeout: 60\_000 \* 60 do

 15 -> 1

 30 -> 2

 45 -> 3

 0 -> 4

 end

 IO.puts(String.duplicate(" ding ding ding dong ", count))

 church\_bell\_chimes()

end

```

[Link to this macro](#cond_wait/2 "Link to this macro")

cond\_wait(opts \\ [], blocks)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it.ex#L247 "View Source")

(macro)

Wait until one of the expressions in the given block evaluates to a truthy value.

Returns the value corresponding with the matching expression, the value of the optional `else`

clause, or a tuple of the form `{:timeout, timeout_milliseconds}`.

The `do` block passed to this macro must be a series of expressions exactly like a built-in

Elixir `cond` expression. Just like a `cond` expression, the embedded expresions will be

evaluated from top to bottom and the first one that is truthy will provide the resulting value of

the expression. The difference with `cond_wait` is that if none of the expressions is initially

truthy it will wait and periodically re-evaluate them until one of them becomes truthy or a

timeout occurs.

An optional `else` clause may also be used to provide the value in case of a timeout. If an

`else` clause is provided and a timeout occurs, then the `else` clause will be evaluated and

the resulting value of the `else` clause becomes the value of the `cond_wait` expression. If no

`else` clause is provided and a timeout occurs, then the value of the `cond_wait` expression is a

tuple of the form `{:timeout, timeout_milliseconds}`.

 Options

----------

See the WaitForIt module documentation for further discussion of these options.

* `:timeout` - the amount of time to wait (in milliseconds) before giving up

* `:frequency` - the polling frequency (in milliseconds) at which to re-evaluate conditions

* `:signal` - disable polling and use a condition variable of the given name instead

* `:pre_wait` - wait for the given number of milliseconds before evaluating conditions for the first time

 Examples

-----------

 Trigger an alarm when any sensors go beyond a threshold:

```

def sound\_the\_alarm do

 WaitForIt.cond\_wait timeout: 60\_000 \* 60 \* 24 do

 read\_sensor(:sensor1) > 9 -> IO.puts("Alarm: :sensor1 too high!")

 read\_sensor(:sensor2) < 100 -> IO.puts("Alarm: :sensor2 too low!")

 read\_sensor(:sensor3) < 0 -> IO.puts("Alarm: :sensor3 below zero!")

 else

 IO.puts("All is good...for now.")

 end

 sound\_the\_alarm()

end

```

[Link to this macro](#signal/1 "Link to this macro")

signal(condition\_var)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it.ex#L277 "View Source")

(macro)

Send a signal to the given condition variable to indicate that any processes waiting on the

condition variable should re-evaluate their wait conditions.

The caller of `signal` must be in the same Elixir module as any waiters on the same condition

variable since the module is used as a namespace for condition variables. This is to prevent

accidental name collisions as well as to enforce good practice for encapsulation.

[Link to this macro](#wait/2 "Link to this macro")

wait(expression, opts \\ [])

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it.ex#L94 "View Source")

(macro)

Wait until the given `expression` evaluates to a truthy value.

Returns `{:ok, value}` or `{:timeout, timeout_milliseconds}`.

 Options

----------

See the WaitForIt module documentation for further discussion of these options.

* `:timeout` - the amount of time to wait (in milliseconds) before giving up

* `:frequency` - the polling frequency (in milliseconds) at which to re-evaluate conditions

* `:signal` - disable polling and use a condition variable of the given name instead

* `:pre_wait` - wait for the given number of milliseconds before evaluating conditions for the first time

 Examples

-----------

 Wait until the top of the hour:

```

WaitForIt.wait Time.utc\_now.minute == 0, frequency: 60\_000, timeout: 60\_000 \* 60

```

 Wait up to one minute for a particular record to appear in the database:

```

case WaitForIt.wait Repo.get(Post, 42), frequency: 1000, timeout: 60\_000 do

 {:ok, data} -> IO.inspect(data)

 {:timeout, timeout} -> IO.puts("Gave up after #{timeout} milliseconds")

end

```





WaitForIt.ConditionVariable — wait\_for\_it v1.3.0

try { if(localStorage.getItem('night-mode') === 'true') document.body.className += ' night-mode'; } catch (e) { }

wait\_for\_it v1.3.0

WaitForIt.ConditionVariable [View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L1 "View Source")

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

[Link to this section](#summary)

 Summary

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

[Functions](#functions)

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

[child\_spec(init\_arg)](#child_spec/1)

Returns a specification to start this module under a supervisor.

[registry()](#registry/0)

[signal(condition\_var)](#signal/1)

[start\_link()](#start_link/0)

[start\_link(opts)](#start_link/1)

[wait(condition\_var, opts \\ [])](#wait/2)

[Link to this section](#functions)

Functions

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

[Link to this function](#child_spec/1 "Link to this function")

child\_spec(init\_arg)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L2 "View Source")

Returns a specification to start this module under a supervisor.

See [`Supervisor`](https://hexdocs.pm/elixir/Supervisor.html).

[Link to this function](#registry/0 "Link to this function")

registry()

==========

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L23 "View Source")

[Link to this function](#signal/1 "Link to this function")

signal(condition\_var)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L25 "View Source")

[Link to this function](#start_link/0 "Link to this function")

start\_link()

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L10 "View Source")

[Link to this function](#start_link/1 "Link to this function")

start\_link(opts)

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L12 "View Source")

[Link to this function](#wait/2 "Link to this function")

wait(condition\_var, opts \\ [])

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

[View Source](https://github.com/jvoegele/wait_for_it/blob/master/lib/wait_for_it/condition_variable.ex#L28 "View Source")

