Merge paradox/scala/agents.md and java/agents.md (#23080)
This commit is contained in:
parent
4bdccd416f
commit
fb3e42f2e8
3 changed files with 54 additions and 112 deletions
|
|
@ -1,93 +0,0 @@
|
||||||
# Agents
|
|
||||||
|
|
||||||
Agents in Akka are inspired by [agents in Clojure](http://clojure.org/agents).
|
|
||||||
|
|
||||||
@@@ warning { title="Deprecation warning" }
|
|
||||||
|
|
||||||
Agents have been deprecated and are scheduled for removal
|
|
||||||
in the next major version. We have found that their leaky abstraction (they do not
|
|
||||||
work over the network) make them inferior to pure Actors, and in face of the soon
|
|
||||||
inclusion of Akka Typed we see little value in maintaining the current Agents.
|
|
||||||
|
|
||||||
@@@
|
|
||||||
|
|
||||||
Agents provide asynchronous change of individual locations. Agents are bound to
|
|
||||||
a single storage location for their lifetime, and only allow mutation of that
|
|
||||||
location (to a new state) to occur as a result of an action. Update actions are
|
|
||||||
functions that are asynchronously applied to the Agent's state and whose return
|
|
||||||
value becomes the Agent's new state. The state of an Agent should be immutable.
|
|
||||||
|
|
||||||
While updates to Agents are asynchronous, the state of an Agent is always
|
|
||||||
immediately available for reading by any thread (using `get`) without any messages.
|
|
||||||
|
|
||||||
Agents are reactive. The update actions of all Agents get interleaved amongst
|
|
||||||
threads in an `ExecutionContext`. At any point in time, at most one `send` action for
|
|
||||||
each Agent is being executed. Actions dispatched to an agent from another thread
|
|
||||||
will occur in the order they were sent, potentially interleaved with actions
|
|
||||||
dispatched to the same agent from other threads.
|
|
||||||
|
|
||||||
## Creating Agents
|
|
||||||
|
|
||||||
Agents are created by invoking `new Agent<ValueType>(value, executionContext)` – passing in the Agent's initial
|
|
||||||
value and providing an `ExecutionContext` to be used for it:
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-agent #create type=java }
|
|
||||||
|
|
||||||
## Reading an Agent's value
|
|
||||||
|
|
||||||
Agents can be dereferenced (you can get an Agent's value) by invoking the Agent
|
|
||||||
with `get()` like this:
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #read-get type=java }
|
|
||||||
|
|
||||||
Reading an Agent's current value does not involve any message passing and
|
|
||||||
happens immediately. So while updates to an Agent are asynchronous, reading the
|
|
||||||
state of an Agent is synchronous.
|
|
||||||
|
|
||||||
You can also get a `Future` to the Agents value, that will be completed after the
|
|
||||||
currently queued updates have completed:
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-future #read-future type=java }
|
|
||||||
|
|
||||||
See @ref:[Futures](futures.md) for more information on `Futures`.
|
|
||||||
|
|
||||||
## Updating Agents (send & alter)
|
|
||||||
|
|
||||||
You update an Agent by sending a function (`akka.dispatch.Mapper`) that transforms the current value or
|
|
||||||
by sending just a new value. The Agent will apply the new value or function
|
|
||||||
atomically and asynchronously. The update is done in a fire-forget manner and
|
|
||||||
you are only guaranteed that it will be applied. There is no guarantee of when
|
|
||||||
the update will be applied but dispatches to an Agent from a single thread will
|
|
||||||
occur in order. You apply a value or a function by invoking the `send`
|
|
||||||
function.
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-function #send type=java }
|
|
||||||
|
|
||||||
You can also dispatch a function to update the internal state but on its own
|
|
||||||
thread. This does not use the reactive thread pool and can be used for
|
|
||||||
long-running or blocking operations. You do this with the `sendOff`
|
|
||||||
method. Dispatches using either `sendOff` or `send` will still be executed
|
|
||||||
in order.
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-function #send-off type=java }
|
|
||||||
|
|
||||||
All `send` methods also have a corresponding `alter` method that returns a `Future`.
|
|
||||||
See @ref:[Futures](futures.md) for more information on `Futures`.
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-future #import-function #alter type=java }
|
|
||||||
|
|
||||||
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-future #import-function #alter-off type=java }
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
There are several configuration properties for the agents module, please refer
|
|
||||||
to the @ref:[reference configuration](general/configuration.md#config-akka-agent).
|
|
||||||
|
|
||||||
## Deprecated Transactional Agents
|
|
||||||
|
|
||||||
Agents participating in enclosing STM transaction is a deprecated feature in 2.3.
|
|
||||||
|
|
||||||
If an Agent is used within an enclosing `Scala STM transaction`, then it will participate in
|
|
||||||
that transaction. If you send to an Agent within a transaction then the dispatch
|
|
||||||
to the Agent will be held until that transaction commits, and discarded if the
|
|
||||||
transaction is aborted.
|
|
||||||
1
akka-docs/src/main/paradox/java/agents.md
Symbolic link
1
akka-docs/src/main/paradox/java/agents.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../scala/agents.md
|
||||||
|
|
@ -18,7 +18,7 @@ functions that are asynchronously applied to the Agent's state and whose return
|
||||||
value becomes the Agent's new state. The state of an Agent should be immutable.
|
value becomes the Agent's new state. The state of an Agent should be immutable.
|
||||||
|
|
||||||
While updates to Agents are asynchronous, the state of an Agent is always
|
While updates to Agents are asynchronous, the state of an Agent is always
|
||||||
immediately available for reading by any thread (using `get` or `apply`)
|
immediately available for reading by any thread (using `get` @scala[or `apply`])
|
||||||
without any messages.
|
without any messages.
|
||||||
|
|
||||||
Agents are reactive. The update actions of all Agents get interleaved amongst
|
Agents are reactive. The update actions of all Agents get interleaved amongst
|
||||||
|
|
@ -38,30 +38,45 @@ read or update the Agent.
|
||||||
|
|
||||||
## Creating Agents
|
## Creating Agents
|
||||||
|
|
||||||
Agents are created by invoking `Agent(value)` passing in the Agent's initial
|
Agents are created by invoking @scala[`Agent(value)`] @java[`new Agent<ValueType>(value, executionContext)`] passing in the Agent's initial
|
||||||
value and providing an implicit `ExecutionContext` to be used for it, for these
|
value and providing an @scala[implicit] `ExecutionContext` to be used for it,
|
||||||
examples we're going to use the default global one, but YMMV:
|
@scala[for these examples we're going to use the default global one, but YMMV:]
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #create }
|
Scala
|
||||||
|
: @@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #create }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-agent #create type=java }
|
||||||
|
|
||||||
## Reading an Agent's value
|
## Reading an Agent's value
|
||||||
|
|
||||||
Agents can be dereferenced (you can get an Agent's value) by invoking the Agent
|
Agents can be dereferenced (you can get an Agent's value) by invoking the Agent
|
||||||
with parentheses like this:
|
with @scala[parentheses] @java[`get()`] like this:
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #read-apply }
|
Scala
|
||||||
|
: @@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #read-apply #read-get }
|
||||||
|
|
||||||
Or by using the get method:
|
Java
|
||||||
|
: @@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #read-get type=java }
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #read-get }
|
|
||||||
|
|
||||||
Reading an Agent's current value does not involve any message passing and
|
Reading an Agent's current value does not involve any message passing and
|
||||||
happens immediately. So while updates to an Agent are asynchronous, reading the
|
happens immediately. So while updates to an Agent are asynchronous, reading the
|
||||||
state of an Agent is synchronous.
|
state of an Agent is synchronous.
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
You can also get a `Future` to the Agents value, that will be completed after the
|
||||||
|
currently queued updates have completed:
|
||||||
|
|
||||||
|
@@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-future #read-future type=java }
|
||||||
|
|
||||||
|
See @ref:[Futures](futures.md) for more information on `Futures`.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
## Updating Agents (send & alter)
|
## Updating Agents (send & alter)
|
||||||
|
|
||||||
You update an Agent by sending a function that transforms the current value or
|
You update an Agent by sending a function @java[(`akka.dispatch.Mapper`)] that transforms the current value or
|
||||||
by sending just a new value. The Agent will apply the new value or function
|
by sending just a new value. The Agent will apply the new value or function
|
||||||
atomically and asynchronously. The update is done in a fire-forget manner and
|
atomically and asynchronously. The update is done in a fire-forget manner and
|
||||||
you are only guaranteed that it will be applied. There is no guarantee of when
|
you are only guaranteed that it will be applied. There is no guarantee of when
|
||||||
|
|
@ -69,7 +84,11 @@ the update will be applied but dispatches to an Agent from a single thread will
|
||||||
occur in order. You apply a value or a function by invoking the `send`
|
occur in order. You apply a value or a function by invoking the `send`
|
||||||
function.
|
function.
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #send }
|
Scala
|
||||||
|
: @@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #send }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-function #send type=java }
|
||||||
|
|
||||||
You can also dispatch a function to update the internal state but on its own
|
You can also dispatch a function to update the internal state but on its own
|
||||||
thread. This does not use the reactive thread pool and can be used for
|
thread. This does not use the reactive thread pool and can be used for
|
||||||
|
|
@ -77,14 +96,22 @@ long-running or blocking operations. You do this with the `sendOff`
|
||||||
method. Dispatches using either `sendOff` or `send` will still be executed
|
method. Dispatches using either `sendOff` or `send` will still be executed
|
||||||
in order.
|
in order.
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #send-off }
|
Scala
|
||||||
|
: @@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #send-off }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-function #send-off type=java }
|
||||||
|
|
||||||
All `send` methods also have a corresponding `alter` method that returns a `Future`.
|
All `send` methods also have a corresponding `alter` method that returns a `Future`.
|
||||||
See @ref:[Futures](futures.md) for more information on `Futures`.
|
See @ref:[`Future`s](futures.md) for more information on `Future`s.
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #alter }
|
Scala
|
||||||
|
: @@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #alter #alter-off }
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #alter-off }
|
Java
|
||||||
|
: @@snip [AgentDocTest.java]($code$/java/jdocs/agent/AgentDocTest.java) { #import-future #import-function #alter #alter-off type=java }
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
## Awaiting an Agent's value
|
## Awaiting an Agent's value
|
||||||
|
|
||||||
|
|
@ -93,7 +120,7 @@ currently queued updates have completed:
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #read-future }
|
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #read-future }
|
||||||
|
|
||||||
See @ref:[Futures](futures.md) for more information on `Futures`.
|
See @ref:[`Future`s](futures.md) for more information on `Future`s.
|
||||||
|
|
||||||
## Monadic usage
|
## Monadic usage
|
||||||
|
|
||||||
|
|
@ -106,6 +133,8 @@ Example of monadic usage:
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #monadic-example }
|
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #monadic-example }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
There are several configuration properties for the agents module, please refer
|
There are several configuration properties for the agents module, please refer
|
||||||
|
|
@ -115,9 +144,13 @@ to the @ref:[reference configuration](general/configuration.md#config-akka-agent
|
||||||
|
|
||||||
Agents participating in enclosing STM transaction is a deprecated feature in 2.3.
|
Agents participating in enclosing STM transaction is a deprecated feature in 2.3.
|
||||||
|
|
||||||
If an Agent is used within an enclosing transaction, then it will participate in
|
If an Agent is used within an enclosing @java[`Scala STM`] transaction, then it will participate in
|
||||||
that transaction. If you send to an Agent within a transaction then the dispatch
|
that transaction. If you send to an Agent within a transaction then the dispatch
|
||||||
to the Agent will be held until that transaction commits, and discarded if the
|
to the Agent will be held until that transaction commits, and discarded if the
|
||||||
transaction is aborted. Here's an example:
|
transaction is aborted. @scala[Here's an example:]
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #transfer-example }
|
@@snip [AgentDocSpec.scala]($code$/scala/docs/agent/AgentDocSpec.scala) { #transfer-example }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
@ -32,6 +32,7 @@ class AgentDocSpec extends AkkaSpec {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
//#read-get
|
//#read-get
|
||||||
|
// Or by using the get method:
|
||||||
val result = agent.get
|
val result = agent.get
|
||||||
//#read-get
|
//#read-get
|
||||||
result should be(0)
|
result should be(0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue