From b877dab11139b51b0699d4867ce66005264627f6 Mon Sep 17 00:00:00 2001 From: Ebere Abanonu Date: Mon, 24 Jan 2022 11:16:19 +0100 Subject: [PATCH] Fixed broken `code` references caused by moving `tutorial*` to a different folder --- .../intro/getting-started/tutorial-1.md | 16 ++++++------- .../intro/getting-started/tutorial-2.md | 14 +++++------ .../intro/getting-started/tutorial-3.md | 20 ++++++++-------- .../intro/getting-started/tutorial-4.md | 24 +++++++++---------- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/articles/intro/getting-started/tutorial-1.md b/docs/articles/intro/getting-started/tutorial-1.md index dc5ab0d4232..e5f7bfb3857 100644 --- a/docs/articles/intro/getting-started/tutorial-1.md +++ b/docs/articles/intro/getting-started/tutorial-1.md @@ -67,8 +67,8 @@ Creating a non-top-level actor is possible from any actor, by invoking `Context.ActorOf()` which has the exact same signature as its top-level counterpart. This is how it looks like in practice: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=print-refs)] -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=print-refs2)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=print-refs)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=print-refs2)] We see that the following two lines are printed @@ -129,8 +129,8 @@ override. The most commonly used are `PreStart()` and `PostStop()`. Again, we can try out all this with a simple experiment: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=start-stop)] -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=start-stop2)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=start-stop)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=start-stop2)] After running it, we get the output @@ -160,8 +160,8 @@ The default _supervisor strategy_ is to stop and restart the child. If you don't change the default strategy all failures result in a restart. We won't change the default strategy in this simple experiment: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=supervise)] -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=supervise2)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=supervise)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/ActorHierarchyExperiments.cs?name=supervise2)] After running the snippet, we see the following output on the console: @@ -225,11 +225,11 @@ the logging facility built into Akka.NET directly. Furthermore, we are using a recommended pattern for creating actors; define a static `Props()` method in the the actor: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/IotSupervisor.cs?name=iot-supervisor)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/IotSupervisor.cs?name=iot-supervisor)] All we need now is to tie this up with a class with the `main` entry point: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial1/IotApp.cs?name=iot-app)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial1/IotApp.cs?name=iot-app)] This application does very little for now, but we have the first actor in place and we are ready to extend it further. diff --git a/docs/articles/intro/getting-started/tutorial-2.md b/docs/articles/intro/getting-started/tutorial-2.md index efe1f0f3bb6..5213ffaaf32 100644 --- a/docs/articles/intro/getting-started/tutorial-2.md +++ b/docs/articles/intro/getting-started/tutorial-2.md @@ -34,7 +34,7 @@ The protocol for obtaining the current temperature from the device actor is rath We need two messages, one for the request, and one for the reply. A first attempt could look like this: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=read-protocol-1)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=read-protocol-1)] This is a fine approach, but it limits the flexibility of the protocol. To understand why we need to talk about message ordering and message delivery guarantees in general. @@ -144,12 +144,12 @@ can be helpful to put an additional query ID field in the message which helps us Hence, we add one more field to our messages, so that an ID can be provided by the requester: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=read-protocol-2)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=read-protocol-2)] Our device actor has the responsibility to use the same ID for the response of a given query. Now we can sketch our device actor: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=device-with-read)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=device-with-read)] We maintain the current temperature, initially set to `null`, and we simply report it back if queried. We also added fields for the ID of the device and the group it belongs to, which we will use later. @@ -157,7 +157,7 @@ added fields for the ID of the device and the group it belongs to, which we will We can already write a simple test for this functionality (we are using xUnit but any other test framework can be used with the Akka.NET Testkit): -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceSpec.cs?name=device-read-test)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceSpec.cs?name=device-read-test)] ## The Write Protocol @@ -167,7 +167,7 @@ As a first attempt, we could model recording the current temperature in the devi Such a message could possibly look like this: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=write-protocol-1)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceInProgress.cs?name=write-protocol-1)] The problem with this approach is that the sender of the record temperature message can never be sure if the message was processed or not. We have seen that Akka.NET does not guarantee delivery of these messages and leaves it to the @@ -177,12 +177,12 @@ Just like in the case of temperature queries and responses, it is a good idea to Putting read and write protocol together, the device actor will look like this: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/Device.cs?name=full-device)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/Device.cs?name=full-device)] We are also responsible for writing a new test case now, exercising both the read/query and write/record functionality together: -[!code-csharp[Main](../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceSpec.cs?name=device-write-read-test)] +[!code-csharp[Main](../../../../src/core/Akka.Docs.Tutorials/Tutorial2/DeviceSpec.cs?name=device-write-read-test)] ## What Is Next? diff --git a/docs/articles/intro/getting-started/tutorial-3.md b/docs/articles/intro/getting-started/tutorial-3.md index e4b98c9aa5d..a09115a7fbf 100644 --- a/docs/articles/intro/getting-started/tutorial-3.md +++ b/docs/articles/intro/getting-started/tutorial-3.md @@ -85,7 +85,7 @@ is known up front: device groups and device actors are created on-demand. The st Now that the steps are defined, we only need to define the messages that we will use to communicate requests and their acknowledgment: -[!code-csharp[DeviceManager.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceManager.cs?name=device-manager-msgs)] +[!code-csharp[DeviceManager.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceManager.cs?name=device-manager-msgs)] As you see, in this case, we have not included a request ID field in the messages. Since registration is usually happening once, at the component that connects the system to some network protocol, we will usually have no use for the ID. @@ -104,7 +104,7 @@ message is preserved in the upper layers.* We will show you in the next section We also add a safeguard against requests that come with a mismatched group or device ID. This is how the resulting the code looks like: -[!code-csharp[Device.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/Device.cs?name=device-with-register)] +[!code-csharp[Device.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/Device.cs?name=device-with-register)] We should not leave features untested, so we immediately write two new test cases, one exercising successful registration, the other testing the case when IDs don't match: @@ -115,7 +115,7 @@ and fails if it receives any messages during this period. If no messages are rec assertion passes. It is usually a good idea to keep these timeouts low (but not too low) because they add significant test execution time otherwise. -[!code-csharp[DeviceSpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceSpec.cs?name=device-registration-tests)] +[!code-csharp[DeviceSpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceSpec.cs?name=device-registration-tests)] ## Device Group @@ -128,18 +128,18 @@ by using `Forward` instead of the `Tell` operator. The only difference between t sender while `Tell` always sets the sender to be the current actor. Just like with our device actor, we ensure that we don't respond to wrong group IDs: -[!code-csharp[DeviceGroup.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupInProgress.cs?name=device-group-register)] +[!code-csharp[DeviceGroup.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupInProgress.cs?name=device-group-register)] Just as we did with the device, we test this new functionality. We also test that the actors returned for the two different IDs are actually different, and we also attempt to record a temperature reading for each of the devices to see if the actors are responding. -[!code-csharp[DeviceGroupSpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-test-registration)] +[!code-csharp[DeviceGroupSpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-test-registration)] It might be, that a device actor already exists for the registration request. In this case, we would like to use the existing actor instead of a new one. We have not tested this yet, so we need to fix this: -[!code-csharp[DeviceGroupSpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-test3)] +[!code-csharp[DeviceGroupSpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-test3)] So far, we have implemented everything for registering device actors in the group. Devices come and go, however, so we will need a way to remove those from the `Dictionary`. We will assume that when a device is removed, its corresponding device actor @@ -164,13 +164,13 @@ its ID, which we need to remove it from the map of existing device to device act need to introduce another placeholder, `Dictionary`, that allow us to find out the device ID corresponding to a given `IActorRef`. Putting this together the result is: -[!code-csharp[DeviceGroup.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupInProgress.cs?name=device-group-remove)] +[!code-csharp[DeviceGroup.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupInProgress.cs?name=device-group-remove)] So far we have no means to get what devices the group device actor keeps track of and, therefore, we cannot test our new functionality yet. To make it testable, we add a new query capability `RequestDeviceList` that simply lists the currently active device IDs: -[!code-csharp[DeviceGroup.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroup.cs?name=device-group-full)] +[!code-csharp[DeviceGroup.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroup.cs?name=device-group-full)] We almost have everything to test the removal of devices. What is missing is: @@ -184,14 +184,14 @@ We add two more test cases now. In the first, we just test that we get back the a few devices. The second test case makes sure that the device ID is properly removed after the device actor has been stopped: -[!code-csharp[DeviceGroupSpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-list-terminate-test)] +[!code-csharp[DeviceGroupSpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceGroupSpec.cs?name=device-group-list-terminate-test)] ## Device Manager The only part that remains now is the entry point for our device manager component. This actor is very similar to the device group actor, with the only difference that it creates device group actors instead of device actors: -[!code-csharp[DeviceManager.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceManager.cs?name=device-manager-full)] +[!code-csharp[DeviceManager.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial3/DeviceManager.cs?name=device-manager-full)] We leave tests of the device manager as an exercise as it is very similar to the tests we have written for the group actor. diff --git a/docs/articles/intro/getting-started/tutorial-4.md b/docs/articles/intro/getting-started/tutorial-4.md index 8fa1afa9e55..391a6c4ff5c 100644 --- a/docs/articles/intro/getting-started/tutorial-4.md +++ b/docs/articles/intro/getting-started/tutorial-4.md @@ -46,7 +46,7 @@ that each device can be in, according to the query: Summarizing these in message types we can add the following to `DeviceGroup`: -[!code-csharp[DeviceGroup.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroup.cs?name=query-protocol)] +[!code-csharp[DeviceGroup.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroup.cs?name=query-protocol)] ## Implementing the Query @@ -90,7 +90,7 @@ until the timeout to mark these as not available. Putting together all these, the outline of our actor looks like this: -[!code-csharp[DeviceGroupQueryInProgress.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQueryInProgress.cs?name=query-outline)] +[!code-csharp[DeviceGroupQueryInProgress.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQueryInProgress.cs?name=query-outline)] The query actor, apart from the pending timer, has one stateful aspect about it: the actors that did not answer so far or, from the other way around, the set of actors that have replied or stopped. One way to track this state is @@ -110,7 +110,7 @@ we will discuss later. In the case of timeout, we need to simply take all the ac (the members of the set `stillWaiting`) and put a `DeviceTimedOut` as the status in the final reply. Then we reply to the submitter of the query with the collected results and stop the query actor: -[!code-csharp[DeviceGroupQuery.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-state)] +[!code-csharp[DeviceGroupQuery.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-state)] What is not yet clear is how we will "mutate" the `answersSoFar` and `stillWaiting` data structures. One important thing to note is that the function `WaitingForReplies` **does not handle the messages directly. It returns an `UntypedReceive` @@ -139,7 +139,7 @@ only the first call will have any effect, the rest is simply ignored. With all this knowledge, we can create the `ReceivedResponse` method: -[!code-csharp[DeviceGroupQuery.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-collect-reply)] +[!code-csharp[DeviceGroupQuery.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-collect-reply)] It is quite natural to ask at this point, what have we gained by using the `Context.Become()` trick instead of just making the `repliesSoFar` and `stillWaiting` structures mutable fields of the actor? In this @@ -153,7 +153,7 @@ with the solution we have used here as it helps structuring more complex actor c Our query actor is now done: -[!code-csharp[DeviceGroupQuery.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-full)] +[!code-csharp[DeviceGroupQuery.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuery.cs?name=query-full)] ## Testing @@ -163,27 +163,27 @@ various normal or failure scenarios. Thankfully we took the list of collaborator to the query actor, so we can easily pass in `TestProbe` references. In our first test, we try out the case when there are two devices and both report a temperature: -[!code-csharp[DeviceGroupQuerySpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-normal)] +[!code-csharp[DeviceGroupQuerySpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-normal)] That was the happy case, but we know that sometimes devices cannot provide a temperature measurement. This scenario is just slightly different from the previous: -[!code-csharp[DeviceGroupQuerySpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-no-reading)] +[!code-csharp[DeviceGroupQuerySpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-no-reading)] We also know, that sometimes device actors stop before answering: -[!code-csharp[DeviceGroupQuerySpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-stopped)] +[!code-csharp[DeviceGroupQuerySpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-stopped)] If you remember, there is another case related to device actors stopping. It is possible that we get a normal reply from a device actor, but then receive a `Terminated` for the same actor later. In this case, we would like to keep the first reply and not mark the device as `DeviceNotAvailable`. We should test this, too: -[!code-csharp[DeviceGroupQuerySpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-stopped-later)] +[!code-csharp[DeviceGroupQuerySpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-stopped-later)] The final case is when not all devices respond in time. To keep our test relatively fast, we will construct the `DeviceGroupQuery` actor with a smaller timeout: -[!code-csharp[DeviceGroupQuerySpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-timeout)] +[!code-csharp[DeviceGroupQuerySpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQuerySpec.cs?name=query-test-timeout)] Our query works as expected now, it is time to include this new functionality in the `DeviceGroup` actor now. @@ -192,7 +192,7 @@ Our query works as expected now, it is time to include this new functionality in Including the query feature in the group actor is fairly simple now. We did all the heavy lifting in the query actor itself, the group actor only needs to create it with the right initial parameters and nothing else. -[!code-csharp[DeviceGroupQueryInProgress.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQueryInProgress.cs?name=query-added)] +[!code-csharp[DeviceGroupQueryInProgress.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupQueryInProgress.cs?name=query-added)] It is probably worth reiterating what we said at the beginning of the chapter: By keeping the temporary state that is only relevant to the query itself in a separate actor we keep the group actor implementation very simple. It delegates @@ -204,4 +204,4 @@ would significantly improve throughput. We close this chapter by testing that everything works together. This test is just a variant of the previous ones, now exercising the group query feature: -[!code-csharp[DeviceGroupSpec.cs](../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupSpec.cs?name=group-query-integration-test)] +[!code-csharp[DeviceGroupSpec.cs](../../../../src/core/Akka.Docs.Tutorials/Tutorial4/DeviceGroupSpec.cs?name=group-query-integration-test)]