Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 21 additions & 123 deletions docs/articles/clustering/distributed-publish-subscribe.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,85 +30,25 @@ You register actors to the local mediator with `DistributedPubSubMediator.Subscr

You publish messages by sending `DistributedPubSubMediator.Publish` message to the local mediator.

Actors are automatically removed from the registry when they are terminated, or you can explicitly remove entries with `DistributedPubSubMediator.Unsubscribe`.
Topic actors are automatically removed from the registry when they are terminated; they are terminated if there are no subscribers for the duration configured by `akka.cluster.pub-sub.removed-time-to-live`, which defaults to 2 minutes. You can change the deadline by setting `removed-time-to-live` to a custom duration.

You can `Unsubscribe` from a topic with `DistributedPubSubMediator.Unsubscribe`.

An example of a subscriber actor:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to turn this into a DocFx ref

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All code samples in this doc need to be updated

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... they are terminated; they are terminated ...

This would read better if it was two separate sentences. Also, the repeated verbiage looks out of place. It could be changed to something like

... they are terminated. Termination occurs when there are no ....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion cc @eaba

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note taken!

```csharp
public class Subscriber : ReceiveActor
{
private readonly ILoggingAdapter log = Context.GetLogger();

public Subscriber()
{
var mediator = DistributedPubSub.Get(Context.System).Mediator;

// subscribe to the topic named "content"
mediator.Tell(new Subscribe("content", Self));

Receive<string>(s =>
{
log.Info($"Got {s}");
});

Receive<SubscribeAck>(subscribeAck =>
{
if (subscribeAck.Subscribe.Topic.Equals("content")
&& subscribeAck.Subscribe.Ref.Equals(Self)
&& subscribeAck.Subscribe.Group == null)
{
log.Info("subscribing");
}
});
}
}
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SamplePublishSubscribe/Subscriber.cs?name=SampleSubscriber)]

Subscriber actors can be started on several nodes in the cluster, and all will receive messages published to the "content" topic.

```csharp
RunOn(() =>
{
Sys.ActorOf(Props.Create<Subscriber>(), "subscriber1");
}, _first);

RunOn(() =>
{
Sys.ActorOf(Props.Create<Subscriber>(), "subscriber2");
Sys.ActorOf(Props.Create<Subscriber>(), "subscriber3");
}, _second);
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SamplePublishSubscribe/Program.cs?name=subscriber)]

A simple actor that publishes to this "content" topic:

```csharp
public class Publisher : ReceiveActor
{
public Publisher()
{
// activate the extension
var mediator = DistributedPubSub.Get(Context.System).Mediator;

Receive<string>(str =>
{
var upperCase = str.ToUpper();
mediator.Tell(new Publish("content", upperCase));
});
}
}
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SamplePublisher/Publisher.cs?name=SamplePublisher)]

It can publish messages to the topic from anywhere in the cluster:

```csharp
RunOn(() =>
{
var publisher = Sys.ActorOf(Props.Create<Publisher>(), "publisher");

// after a while the subscriptions are replicated
publisher.Tell("hello");
}, _third);
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SamplePublisher/Program.cs?name=publisher)]

### Topic Groups

Expand All @@ -135,76 +75,34 @@ Actors are automatically removed from the registry when they are terminated, or

An example of a destination actor:

```csharp
public class Destination : ReceiveActor
{
private readonly ILoggingAdapter log = Context.GetLogger();

public Destination()
{
// activate the extension
var mediator = DistributedPubSub.Get(Context.System).Mediator;

// register to the path
mediator.Tell(new Put(Self));

Receive<string>(s =>
{
log.Info($"Got {s}");
});
}
}
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SampleDestination/Destination.cs?name=SampleDestination)]

Destination actors can be started on several nodes in the cluster, and all will receive messages sent to the path (without address information).

```csharp
RunOn(() =>
{
Sys.ActorOf(Props.Create<Destination>(), "destination");
}, _first);

RunOn(() =>
{
Sys.ActorOf(Props.Create<Destination>(), "destination");
}, _second);
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SampleDestination/Program.cs?name=destination)]

A simple actor that sends to the path:

```csharp
public class Sender : ReceiveActor
{
public Sender()
{
// activate the extension
var mediator = DistributedPubSub.Get(Context.System).Mediator;

Receive<string>(str =>
{
var upperCase = str.ToUpper();
mediator.Tell(new Send(path: "/user/destination", message: upperCase, localAffinity: true));
});
}
}
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SampleSender/Sender.cs?name=samplesender)]

It can send messages to the path from anywhere in the cluster:

```csharp
RunOn(() =>
{
var sender = Sys.ActorOf(Props.Create<Sender>(), "sender");

// after a while the destinations are replicated
sender.Tell("hello");
}, _third);
```
[!code-csharp[Main](../../../src/examples/Cluster/PublishSubscribe/SampleSender/Program.cs?name=sender)]

It is also possible to broadcast messages to the actors that have been registered with `Put`. Send `DistributedPubSubMediator.SendToAll` message to the local mediator and the wrapped message will then be delivered to all recipients with a matching path. Actors with the same path, without address information, can be registered on different nodes. On each node there can only be one such actor, since the path is unique within one local actor system.

Typical usage of this mode is to broadcast messages to all replicas with the same path, e.g. 3 actors on different nodes that all perform the same actions, for redundancy. You can also optionally specify a property (`AllButSelf`) deciding if the message should be sent to a matching path on the self node or not.

## DeadLetters From `DistributedPubSub`

There are three factors that determine when or if a message is published to `/system/deadletters`, namely: `send-to-dead-letters-when-no-subscribers`, zero existing subscribers, or if the topic does not exist / has been terminated.

* **`akka.cluster.pub-sub.send-to-dead-letters-when-no-subscribers`**: this is a `DistributedPubSub` setting that, if turned off or set to `false` (it is `on`/`true` by default), will not produce `Deadletter`s when there are no subscribers or the topic does not exist.

* **Zero Existing Subscribers**: A message is sent to the DeadLetter if **`Send-to-dead-letters-when-no-subscribers`** is on/true and there are no existing subscriber(s) to receive it. `Akka.Cluster.DistributedPubSub` does not support queueing up messages while there are no existing subscribers!

* **Terminated Topic Actor**: When there are no existing subscribers and no new subscription for a duration of, say 2 minutes (the default for `removed-time-to-live`), the Topic Actor is terminated and if **`Send-to-dead-letters-when-no-subscribers`** is on/true, messages are sent to DeadLetter.

## DistributedPubSub Extension

In the example above the mediator is started and accessed with the `Akka.Cluster.Tools.PublishSubscribe.DistributedPubSub` extension. That is convenient and perfectly fine in most cases, but it can be good to know that it is possible to start the mediator actor as an ordinary actor and you can have several different mediators at the same time to be able to divide a large number of actors/topics to different mediators. For example you might want to use different cluster roles for different mediators.
Expand Down
3 changes: 2 additions & 1 deletion docs/cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@
"mergetool",
"titlecase",
"Varghese",
"Vertech"
"Vertech",
"DeadLetter"
],
"ignoreRegExpList": [
"\\((.*)\\)", // Markdown links
Expand Down
79 changes: 71 additions & 8 deletions src/Akka.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29911.84
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmark", "Benchmark", "{73108242-625A-4D7B-AA09-63375DBAE464}"
EndProject
Expand Down Expand Up @@ -244,19 +244,29 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SerializationBenchmarks", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DDataStressTest", "examples\Cluster\DData\DDataStressTest\DDataStressTest.csproj", "{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Benchmarks", "benchmark\Akka.Cluster.Benchmarks\Akka.Cluster.Benchmarks.csproj", "{3CEBB0AE-6A88-4C32-A1D3-A8FB1E7E236B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Benchmarks", "benchmark\Akka.Cluster.Benchmarks\Akka.Cluster.Benchmarks.csproj", "{3CEBB0AE-6A88-4C32-A1D3-A8FB1E7E236B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sharding", "Sharding", "{CF2704C6-3A27-450F-9C60-081341D88C1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoppingCart", "examples\Cluster\ClusterSharding\ShoppingCart\ShoppingCart.csproj", "{9F8CCEDE-E871-473A-9C9A-DDDDE69E5130}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShoppingCart", "examples\Cluster\ClusterSharding\ShoppingCart\ShoppingCart.csproj", "{9F8CCEDE-E871-473A-9C9A-DDDDE69E5130}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Persistence", "Persistence", "{A640E39E-F45C-4AE9-AABF-7F1432D357DA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Custom", "examples\Akka.Persistence.Custom\Akka.Persistence.Custom.csproj", "{B9091AE9-B257-4D3A-A9BC-EE2B43AF57A8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Custom", "examples\Akka.Persistence.Custom\Akka.Persistence.Custom.csproj", "{B9091AE9-B257-4D3A-A9BC-EE2B43AF57A8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.Custom.Tests", "examples\Akka.Persistence.Custom.Tests\Akka.Persistence.Custom.Tests.csproj", "{F6C974B8-48F8-41C7-95AC-3CFAA720E0E4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.Custom.Tests", "examples\Akka.Persistence.Custom.Tests\Akka.Persistence.Custom.Tests.csproj", "{F6C974B8-48F8-41C7-95AC-3CFAA720E0E4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Cluster.Cpu.Benchmark", "benchmark\Akka.Cluster.Cpu.Benchmark\Akka.Cluster.Cpu.Benchmark.csproj", "{6FA94D22-9369-4A60-BBC1-764CA68F4ED1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Cluster.Cpu.Benchmark", "benchmark\Akka.Cluster.Cpu.Benchmark\Akka.Cluster.Cpu.Benchmark.csproj", "{6FA94D22-9369-4A60-BBC1-764CA68F4ED1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PublishSubscribe", "PublishSubscribe", "{51C887A7-7A69-43E2-9BE2-17016E2D8476}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleSubscriber", "examples\Cluster\PublishSubscribe\SamplePublishSubscribe\SampleSubscriber.csproj", "{F8BA242A-AEA4-46AC-BA08-C11C5624256D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamplePublisher", "examples\Cluster\PublishSubscribe\SamplePublisher\SamplePublisher.csproj", "{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleDestination", "examples\Cluster\PublishSubscribe\SampleDestination\SampleDestination.csproj", "{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleSender", "examples\Cluster\PublishSubscribe\SampleSender\SampleSender.csproj", "{A5392607-15B8-4869-BB20-FAAD4D09E08B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -1209,6 +1219,54 @@ Global
{6FA94D22-9369-4A60-BBC1-764CA68F4ED1}.Release|x64.Build.0 = Release|Any CPU
{6FA94D22-9369-4A60-BBC1-764CA68F4ED1}.Release|x86.ActiveCfg = Release|Any CPU
{6FA94D22-9369-4A60-BBC1-764CA68F4ED1}.Release|x86.Build.0 = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|x64.ActiveCfg = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|x64.Build.0 = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|x86.ActiveCfg = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Debug|x86.Build.0 = Debug|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|Any CPU.Build.0 = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|x64.ActiveCfg = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|x64.Build.0 = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|x86.ActiveCfg = Release|Any CPU
{F8BA242A-AEA4-46AC-BA08-C11C5624256D}.Release|x86.Build.0 = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|x64.ActiveCfg = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|x64.Build.0 = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|x86.ActiveCfg = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Debug|x86.Build.0 = Debug|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|Any CPU.Build.0 = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|x64.ActiveCfg = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|x64.Build.0 = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|x86.ActiveCfg = Release|Any CPU
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724}.Release|x86.Build.0 = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|x64.ActiveCfg = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|x64.Build.0 = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|x86.ActiveCfg = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Debug|x86.Build.0 = Debug|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|Any CPU.Build.0 = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|x64.ActiveCfg = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|x64.Build.0 = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|x86.ActiveCfg = Release|Any CPU
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320}.Release|x86.Build.0 = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|x64.ActiveCfg = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|x64.Build.0 = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Debug|x86.Build.0 = Debug|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|Any CPU.Build.0 = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|x64.ActiveCfg = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|x64.Build.0 = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|x86.ActiveCfg = Release|Any CPU
{A5392607-15B8-4869-BB20-FAAD4D09E08B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1280,6 +1338,7 @@ Global
{99CCB7CA-E1EE-4497-BF52-2200A0EC5CB1} = {76F58DC4-19F1-43EF-A6E2-EC1CC8395AC5}
{5AA81B79-34DD-4DD7-9D40-A5CA389786DF} = {73108242-625A-4D7B-AA09-63375DBAE464}
{C50E1A9E-820C-4E75-AE39-6F96A99AC4A7} = {D3AF8295-AEB5-4324-AA82-FCC0014AC310}
{3C6EB4EF-3726-432F-812E-07828876418B} = {CF2704C6-3A27-450F-9C60-081341D88C1D}
{AF50BDA2-EA1C-4694-9B0C-CB5D50024181} = {D3AF8295-AEB5-4324-AA82-FCC0014AC310}
{6389B968-FFBE-44AF-9016-687E837D555B} = {AF50BDA2-EA1C-4694-9B0C-CB5D50024181}
{91B73868-F504-45F2-B49F-9F967D692230} = {AF50BDA2-EA1C-4694-9B0C-CB5D50024181}
Expand Down Expand Up @@ -1317,12 +1376,16 @@ Global
{44B3DDD6-6103-4E8F-8AC2-0F4BA3CF6B50} = {C50E1A9E-820C-4E75-AE39-6F96A99AC4A7}
{3CEBB0AE-6A88-4C32-A1D3-A8FB1E7E236B} = {73108242-625A-4D7B-AA09-63375DBAE464}
{CF2704C6-3A27-450F-9C60-081341D88C1D} = {C50E1A9E-820C-4E75-AE39-6F96A99AC4A7}
{3C6EB4EF-3726-432F-812E-07828876418B} = {CF2704C6-3A27-450F-9C60-081341D88C1D}
{9F8CCEDE-E871-473A-9C9A-DDDDE69E5130} = {CF2704C6-3A27-450F-9C60-081341D88C1D}
{A640E39E-F45C-4AE9-AABF-7F1432D357DA} = {D3AF8295-AEB5-4324-AA82-FCC0014AC310}
{B9091AE9-B257-4D3A-A9BC-EE2B43AF57A8} = {A640E39E-F45C-4AE9-AABF-7F1432D357DA}
{F6C974B8-48F8-41C7-95AC-3CFAA720E0E4} = {A640E39E-F45C-4AE9-AABF-7F1432D357DA}
{6FA94D22-9369-4A60-BBC1-764CA68F4ED1} = {73108242-625A-4D7B-AA09-63375DBAE464}
{51C887A7-7A69-43E2-9BE2-17016E2D8476} = {C50E1A9E-820C-4E75-AE39-6F96A99AC4A7}
{F8BA242A-AEA4-46AC-BA08-C11C5624256D} = {51C887A7-7A69-43E2-9BE2-17016E2D8476}
{3AF9CF2D-6C20-4CFE-BC0A-CA48F60E2724} = {51C887A7-7A69-43E2-9BE2-17016E2D8476}
{09CFD060-C7DC-49CC-A6C6-D3FE341A7320} = {51C887A7-7A69-43E2-9BE2-17016E2D8476}
{A5392607-15B8-4869-BB20-FAAD4D09E08B} = {51C887A7-7A69-43E2-9BE2-17016E2D8476}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {03AD8E21-7507-4E68-A4E9-F4A7E7273164}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#region SampleDestination
using Akka.Actor;
using Akka.Cluster.Tools.PublishSubscribe;
using Akka.Event;

namespace SampleDestination
{
public sealed class Destination : ReceiveActor
{
private readonly ILoggingAdapter log = Context.GetLogger();

public Destination()
{
// activate the extension
var mediator = DistributedPubSub.Get(Context.System).Mediator;

// register to the path
mediator.Tell(new Put(Self));

Receive<string>(s =>
{
log.Info($"Got {s}");
});
}
}
#endregion
}
28 changes: 28 additions & 0 deletions src/examples/Cluster/PublishSubscribe/SampleDestination/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#region destination
// See https://aka.ms/new-console-template for more information
using Akka.Actor;
using Akka.Cluster.Tools.PublishSubscribe;
using Akka.Configuration;
using SampleDestination;
var config = ConfigurationFactory.ParseString(@"
akka {
actor.provider = cluster
extensions = [""Akka.Cluster.Tools.PublishSubscribe.DistributedPubSubExtensionProvider,Akka.Cluster.Tools""]
remote {
dot-netty.tcp {
port = 0
hostname = localhost
}
}
cluster {
seed-nodes = [""akka.tcp://cluster@localhost:5800""]
}
}");
var actorSystem = ActorSystem.Create("cluster", config);

DistributedPubSub.Get(actorSystem);

actorSystem.ActorOf(Props.Create<Destination>(), "destination");

actorSystem.WhenTerminated.Wait();
#endregion
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\..\contrib\cluster\Akka.Cluster.Tools\Akka.Cluster.Tools.csproj" />
<ProjectReference Include="..\..\..\..\core\Akka.Cluster\Akka.Cluster.csproj" />
<ProjectReference Include="..\..\..\..\core\Akka\Akka.csproj" />
</ItemGroup>

</Project>
Loading