3
3
<a href =" https://www.swimos.org " ><img src =" https://docs.swimos.org/readme/marlin-blue.svg " align =" left " ></a >
4
4
<br ><br ><br ><br >
5
5
6
- ## ⚠️🚧 Warning: Project is still under construction 👷 🚧
6
+ The Swim Rust SDK contains software framework for building stateful applications that can be interacted
7
+ with via multiplexed streaming APIs. It is built on top of the [ Tokio asynchronous runtime] ( https://tokio.rs/ )
8
+ and a Tokio runtime is required for any Swim application.
7
9
8
- This project is still in its early stages of development, meaning that it is not yet stable and is subject to frequent API changes.
10
+ Each application consists of some number of stateful agents, each of which runs as a separate Tokio task
11
+ and can be individually addressed by a URI. An agent may have both public and private state which can either
12
+ be held solely in memory or, optionally, in persistent storage. The public state of the agent consists of a
13
+ number of lanes, analogous to a field in a record. There are multiple kinds of lanes that, for example, lanes
14
+ containing single values and those containing a map of key-value pairs.
9
15
10
- ** USE AT YOUR OWN RISK!**
16
+ The state of any lane can be observed by establishing a link to it (either from another agent instance or a
17
+ dedicated client). A established link will push all updates to the state of that lane to the subscriber and
18
+ will also allow the subscriber to request changes to the state (for lane kinds that support this). Links
19
+ operate over a web-socket connection and are multiplexed, meaning that links to multiple lanes on the same
20
+ host can share a single web-socket connection.
11
21
12
22
## Usage Guides
13
23
@@ -17,25 +27,85 @@ This project is still in its early stages of development, meaning that it is not
17
27
18
28
## Examples
19
29
20
- TODO
21
- ## Development
30
+ The following example application runs a SwimOS server that hosts a single agent route where each agent instance
31
+ has single lane, called ` lane ` . Each time a changes is made to the lane, it will be printed on the console by the
32
+ server.
33
+
34
+ ``` rust
35
+ use swimos :: {
36
+ agent :: {
37
+ agent_lifecycle :: HandlerContext ,
38
+ agent_model :: AgentModel ,
39
+ event_handler :: {EventHandler , HandlerActionExt },
40
+ lanes :: ValueLane ,
41
+ lifecycle, AgentLaneModel ,
42
+ },
43
+ route :: RoutePattern ,
44
+ server :: {until_termination, Server , ServerBuilder },
45
+ };
46
+
47
+ #[tokio:: main]
48
+ pub async fn main () -> Result <(), Box <dyn std :: error :: Error >> {
49
+
50
+ // An agent route consists of the agent definition and a lifecycle.
51
+ let model = AgentModel :: new (ExampleAgent :: default , ExampleLifecycle . into_lifecycle ());
52
+
53
+ let server = ServerBuilder :: with_plane_name (" Example Plane" )
54
+ . set_bind_addr (" 127.0.0.1:8080" . parse ()? ) // Bind the server to this address.
55
+ . add_route (RoutePattern :: parse_str (" /examples/{id}" )? , model ) // Register the agent we have defined.
56
+ . build ()
57
+ . await ? ;
58
+
59
+ // Run the server until we terminate it with Ctrl-C.
60
+ let (task , handle ) = server . run ();
61
+ let (ctrl_c_result , server_result ) = tokio :: join! (until_termination (handle , None ), task );
22
62
23
- ### Dependencies
24
- [ Formatting ] ( https://github.com/rust-lang/rustfmt ) : ` rustup component add rustfmt ` < br >
25
- [ Clippy ] ( https://github.com/rust-lang/rust-clippy ) : ` rustup component add clippy ` < br >
26
- [ Tarpaulin ] ( https://github.com/xd009642/tarpaulin ) ` cargo install cargo-tarpaulin ` < br >
63
+ ctrl_c_result ? ;
64
+ server_result ? ;
65
+ Ok (())
66
+ }
27
67
28
- ### Unit tests
29
- ##### Basic: ` cargo test `
30
- ##### With coverage: ` cargo tarpaulin --ignore-tests -o Html -t 300 `
68
+ // Deriving the `AgentLaneModel` trait makes this type into an agent.
69
+ #[derive(AgentLaneModel )]
70
+ struct ExampleAgent {
71
+ lane : ValueLane <i32 >,
72
+ }
31
73
32
- ### Lint
33
- ##### Manual
34
- 1 ) ` cargo fmt --all -- --check `
35
- 2 ) ` cargo clippy --all-features --workspace --all-targets -- -D warnings `
74
+ // Any agent type can have any number of lifecycles defined for it. A lifecycle describes
75
+ // how the agent will react to events that occur as it executes.
76
+ #[derive( Default , Clone , Copy )]
77
+ struct ExampleLifecycle ;
36
78
37
- ##### Automatic (before commit):
38
- - Install hook: ` sh ./install-commit-hook.sh `
39
- - Remove hook: ` sh ./remove-commit-hook.sh `
79
+ // The `lifecycle` macro creates an method called `into_lifecycle` for the type, using the
80
+ // annotated event handlers methods in the block.
81
+ #[lifecycle(ExampleAgent )]
82
+ impl ExampleLifecycle {
83
+
84
+ #[on_event(lane)]
85
+ fn lane_event (
86
+ & self ,
87
+ context : HandlerContext <ExampleAgent >,
88
+ value : & i32 ,
89
+ ) -> impl EventHandler <ExampleAgent > {
90
+ let n = * value ;
91
+ context . get_agent_uri (). and_then (move | uri | {
92
+ context . effect (move || {
93
+ println! (" Received value: {} for 'lane' on agent at URI: {}." , n , uri );
94
+ })
95
+ })
96
+ }
97
+
98
+ }
99
+ ```
100
+
101
+ For example, if a Swim client sends an update, with the value ` 5 ` , to the agent at the URI ` /examples/name ` for the
102
+ lane ` lane ` , an instance of ` ExampleAgent ` , using ` ExampleLifecycle ` , will be started by the server. The value of the
103
+ lane will then be set to ` 5 ` and the following will be printed on the console:
104
+
105
+ ```
106
+ Received value: 5 for 'lane' on agent at URI: /examples/name.
107
+ ```
108
+
109
+ ## Development
40
110
41
- Note: The pre-commit hooks take a while to run all checks .
111
+ See the [ development guide ] ( DEVELOPMENT.md ) .
0 commit comments