diff --git a/cmd/nbe/docs.go b/cmd/nbe/docs.go index 285aa97a..1141df18 100644 --- a/cmd/nbe/docs.go +++ b/cmd/nbe/docs.go @@ -27,7 +27,7 @@ var ( Deno, Node, Rust, - CSharp, + DotNet, Java, Ruby, Elixir, @@ -389,6 +389,8 @@ func chromaFormat(code, lang string) (string, error) { lang = "js" case WebSocket: lang = "js" + case DotNet: + lang = "cs" } lexer := lexers.Get(lang) diff --git a/cmd/nbe/parse.go b/cmd/nbe/parse.go index 90b13b5f..227fd1b0 100644 --- a/cmd/nbe/parse.go +++ b/cmd/nbe/parse.go @@ -21,7 +21,7 @@ const ( Go = "go" Rust = "rust" Java = "java" - CSharp = "csharp" + DotNet = "dotnet" Deno = "deno" Node = "node" Bun = "bun" @@ -40,7 +40,7 @@ var ( Go: "Go", Rust: "Rust", Java: "Java", - CSharp: "C#", + DotNet: "C#", Deno: "Deno", Node: "Node", Bun: "Bun", @@ -63,6 +63,7 @@ var ( Node: "main.js", WebSocket: "main.js", Java: "Main.java", + DotNet: "Main.cs", } languageMultiCommentDelims = map[string][2]string{ @@ -70,7 +71,7 @@ var ( // TODO: java has a few conventions.. // https://www.oracle.com/java/technologies/javase/codeconventions-comments.html Java: {"/*", "*/"}, - CSharp: {"/**", "**/"}, + DotNet: {"/**", "**/"}, Deno: {"/*", "*/"}, Node: {"/*", "*/"}, Bun: {"/*", "*/"}, @@ -84,7 +85,7 @@ var ( Go: "//", Rust: "//", Java: "//", - CSharp: "///", + DotNet: "//", Deno: "//", Node: "//", Bun: "//", @@ -162,10 +163,12 @@ var ( // One limitiation is that it does not currently handle trailing multi-line // comments, such as: -// func() int {/* -// a := 1 -// */ -// b := 2 +// +// func() int {/* +// a := 1 +// */ +// b := 2 +// // Since this code is scoped to well written examples, it should not be an issue // in practice. func parseLineType(lang, line string) LineType { @@ -183,7 +186,7 @@ func parseLineType(lang, line string) LineType { } return NormalLine - case Go, CSharp, Java, Rust, C, Deno, Node, Bun: + case Go, DotNet, Java, Rust, C, Deno, Node, Bun: if cStyleSingleCommentLineRe.MatchString(line) { return SingleCommentLine } diff --git a/docker/dotnet/Dockerfile b/docker/dotnet/Dockerfile new file mode 100644 index 00000000..081a62ff --- /dev/null +++ b/docker/dotnet/Dockerfile @@ -0,0 +1,17 @@ +# https://hub.docker.com/_/microsoft-dotnet +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /source + +# copy csproj and restore as distinct layers +COPY *.csproj . +RUN dotnet restore --use-current-runtime + +# copy and publish app and libraries +COPY . . +RUN dotnet publish -c Release -o /app --use-current-runtime --self-contained false --no-restore + +# final stage/image +FROM mcr.microsoft.com/dotnet/runtime:7.0 +WORKDIR /app +COPY --from=build /app . +ENTRYPOINT ["dotnet", "example.dll"] diff --git a/docker/dotnet/example.csproj b/docker/dotnet/example.csproj new file mode 100644 index 00000000..09fa9606 --- /dev/null +++ b/docker/dotnet/example.csproj @@ -0,0 +1,15 @@ + + + + Exe + net7.0 + NATS by Example + enable + false + + + + + + + diff --git a/examples/issues/3724/cli/Dockerfile b/examples/issues/3724/cli/Dockerfile new file mode 100644 index 00000000..39dc7992 --- /dev/null +++ b/examples/issues/3724/cli/Dockerfile @@ -0,0 +1,29 @@ +FROM golang:1.19-alpine3.17 AS build + +RUN go install github.com/nats-io/natscli/nats@latest #allow-online-peer-remove +RUN go install github.com/nats-io/nats-server/v2@main + +FROM natsio/nats-box:0.13.2 + +RUN apk add bash curl + +COPY --from=build /go/bin/nats-server /usr/local/bin/ +COPY --from=build /go/bin/nats /usr/local/bin/ + +COPY . . + +ENTRYPOINT ["bash"] + +CMD ["main.sh"] + +#FROM natsio/nats-box:0.13.3 + +#RUN apk add bash curl + +#COPY --from=nats:2.9.10 /nats-server /usr/local/bin/ + +#COPY . . + +#ENTRYPOINT ["bash"] + +#CMD ["main.sh"] diff --git a/examples/issues/3724/cli/main.sh b/examples/issues/3724/cli/main.sh new file mode 100644 index 00000000..2591ec87 --- /dev/null +++ b/examples/issues/3724/cli/main.sh @@ -0,0 +1,413 @@ +#!/bin/bash + +set -euo pipefail + +unset NATS_URL + +cat <<- EOF > a_1.conf +cluster: { + name: hengli + port: 15333 + routes: [nats-route://127.0.0.1:15333,nats-route://127.0.0.1:15334,nats-route://127.0.0.1:15335] +} +http_port: 18222 +jetstream: { + domain: hengli + store_dir: "./jetstream/hengli_1" +} +leafnodes: { + port: 14333 + remotes: [{ + account: hengli + urls: [nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24333,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24334,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24335] + }] +} +port: 14222 +server_name: hengli_1 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_} + {user: hengli, password: hengli, permissions: { + publish: { + allow:["hengli.to.wsw.test","\$JS.API.>"] + }, + subscribe: { + allow:["\$JS.ACK.hengli_to_wsw_test.>","_INBOX.>"] + } + }} + ] + } +} +EOF + +cat <<- EOF > a_2.conf +cluster: { + name: hengli + port: 15334 + routes: [nats-route://127.0.0.1:15333,nats-route://127.0.0.1:15334,nats-route://127.0.0.1:15335] +} +http_port: 18223 +jetstream: { + domain: hengli + store_dir: "./jetstream/hengli_2" +} +leafnodes: { + port: 14334 + remotes: [{ + account: hengli + urls: [nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24333,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24334,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24335] + }] +} +port: 14223 +server_name: hengli_2 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_}, + {user: hengli, password: hengli, permissions: { + publish: { + allow:["hengli.to.wsw.test","\$JS.API.>"] + }, + subscribe: { + allow:["\$JS.ACK.hengli_to_wsw_test.>","_INBOX.>"] + } + }} + ] + } +} +EOF + +# Define the server configs for cluster. +cat <<- EOF > "a_3.conf" + +cluster: { + name: hengli + port: 15335 + routes: [nats-route://127.0.0.1:15333,nats-route://127.0.0.1:15334,nats-route://127.0.0.1:15335] +} +http_port: 18224 +jetstream: { + domain: hengli + store_dir: "./jetstream/hengli_3" +} +leafnodes: { + port: 14335 + remotes: [{ + account: hengli + urls: [nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24333,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24334,nats-leaf://_hengliConnUser_:_hengliConnUser_@127.0.0.1:24335] + }] +} +port: 14224 +server_name: hengli_3 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_}, + {user: hengli, password: hengli, permissions: { + publish: { + allow:["hengli.to.wsw.test","\$JS.API.>"] + }, + subscribe: { + allow:["\$JS.ACK.hengli_to_wsw_test.>","_INBOX.>"] + } + }} + ] + } +} +EOF + +# Setup the hub cluster. +cat <<- EOF > "b_1.conf" +http_port: 28222 +cluster: { + name: wsw + port: 25333 + routes: [nats-route://127.0.0.1:25333,nats-route://127.0.0.1:25334,nats-route://127.0.0.1:25335] +} +jetstream: { + domain: wsw + store_dir: "./jetstream/wsw_1" +} +leafnodes: { + port: 24333 +} +port: 24222 +server_name: wsw_1 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_} + ] + exports:[ + {service: "\$JS.hengli.API.>", response: stream}, + {service: "\$JS.FC.>"}, + {stream: "deliver.hengli.wsw.>", accounts: ["wsw"]} + ] + }, + wsw: { + jetstream: enabled + users:[ + {user: _wswConnUser_, password: _wswConnUser_}, + {user: wsw, password: wsw, permissions: { + publish: { + allow:["\$JS.ACK.hengli_to_wsw_test.>"] + }, + subscribe: { + allow:["_recv_wsw.hengli.to.wsw.test"] + } + }} + ] + imports:[ + {service: {account:"hengli", subject: "\$JS.hengli.API.>"}, to: "\$JS.hengli.wsw.API.>"}, + {service: {account: "hengli", subject: "\$JS.FC.>"}}, + {stream: {account:"hengli", subject:"deliver.hengli.wsw.>"}} + ] + } +} +EOF + +cat <<- EOF > "b_2.conf" + +cluster: { + name: wsw + port: 25334 + routes: [nats-route://127.0.0.1:25333,nats-route://127.0.0.1:25334,nats-route://127.0.0.1:25335] +} +jetstream: { + domain: wsw + store_dir: "./jetstream/wsw_2" +} +leafnodes: { + port: 24334 +} +port: 24223 +server_name: wsw_2 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_} + ] + exports:[ + {service: "\$JS.hengli.API.>", response: stream}, + {service: "\$JS.FC.>"}, + {stream: "deliver.hengli.wsw.>", accounts: ["wsw"]} + ] + }, + wsw: { + jetstream: enabled + users:[ + {user: _wswConnUser_, password: _wswConnUser_}, + {user: wsw, password: wsw, permissions: { + publish: { + allow:["\$JS.ACK.hengli_to_wsw_test.>"] + }, + subscribe: { + allow:["_recv_wsw.hengli.to.wsw.test"] + } + }} + ] + imports:[ + {service: {account:"hengli", subject: "\$JS.hengli.API.>"}, to: "\$JS.hengli.wsw.API.>"}, + {service: {account: "hengli", subject: "\$JS.FC.>"}}, + {stream: {account:"hengli", subject:"deliver.hengli.wsw.>"}} + ] + } +} +EOF + +cat <<- EOF > "b_3.conf" +cluster: { + name: wsw + port: 25335 + routes: [nats-route://127.0.0.1:25333,nats-route://127.0.0.1:25334,nats-route://127.0.0.1:25335] +} +jetstream: { + domain: wsw + store_dir: "./jetstream/wsw_3" +} +leafnodes: { + port: 24335 +} +port: 24224 +server_name: wsw_3 + +accounts: { + hengli: { + jetstream: enabled + users:[ + {user: _hengliConnUser_, password: _hengliConnUser_} + ] + exports:[ + {service: "\$JS.hengli.API.>", response: stream}, + {service: "\$JS.FC.>"}, + {stream: "deliver.hengli.wsw.>", accounts: ["wsw"]} + ] + }, + wsw: { + jetstream: enabled + users:[ + {user: _wswConnUser_, password: _wswConnUser_}, + {user: wsw, password: wsw, permissions: { + publish: { + allow:["\$JS.ACK.hengli_to_wsw_test.>"] + }, + subscribe: { + allow:["_recv_wsw.hengli.to.wsw.test"] + } + }} + ] + imports:[ + {service: {account:"hengli", subject: "\$JS.hengli.API.>"}, to: "\$JS.hengli.wsw.API.>"}, + {service: {account: "hengli", subject: "\$JS.FC.>"}}, + {stream: {account:"hengli", subject:"deliver.hengli.wsw.>"}} + ] + } +} +EOF + +# ### Bring up the cluster + +# Start a server for each configuration and sleep a second in +# between so the seeds can startup and get healthy. +echo "Starting b_1..." +nats-server -c b_1.conf -P b_1.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting b_2..." +nats-server -c b_2.conf -P b_2.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting b_3..." +nats-server -c b_3.conf -P b_3.pid > /dev/null 2>&1 & +sleep 1 + +# Wait until the servers up and healthy. +echo 'Hub cluster healthy?' +curl --fail --silent \ + --retry 5 \ + --retry-delay 2 \ + http://localhost:28222/healthz; echo + +echo "Starting a_1..." +nats-server -c a_1.conf -P a_1.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting a_2..." +nats-server -c a_2.conf -P a_2.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting a_3..." +nats-server -c a_3.conf -P a_3.pid > /dev/null 2>&1 & +sleep 1 + + +# Wait until the servers up and healthy. +echo 'Leaf cluster healthy?' +curl --fail --silent \ + --retry 5 \ + --retry-delay 2 \ + http://localhost:18222/healthz; echo + +cat <<- EOF > origin-stream.json +{ + "name": "hengli_to_wsw_test", + "subjects": [ + "hengli.to.wsw.test" + ], + "retention": "limits", + "max_consumers": -1, + "max_msgs": -1, + "max_bytes": -1, + "max_age": 0, + "max_msgs_per_subject": -1, + "max_msg_size": -1, + "discard": "old", + "storage": "file", + "num_replicas": 2, + "duplicate_window": 120000000000, + "allow_direct": false, + "mirror_direct": false, + "sealed": false, + "deny_delete": false, + "deny_purge": false, + "allow_rollup_hdrs": false +} +EOF + +cat <<- EOF > mirror-stream.json +{ + "name": "_mirror_hengli_to_wsw_test_hengli", + "retention": "limits", + "max_consumers": -1, + "max_msgs": -1, + "max_bytes": -1, + "max_age": 3600000000000, + "max_msgs_per_subject": -1, + "max_msg_size": -1, + "discard": "old", + "storage": "file", + "num_replicas": 2, + "mirror": { + "name": "hengli_to_wsw_test", + "external": { + "api": "\$JS.hengli.wsw.API", + "deliver": "deliver.hengli.wsw" + } + }, + "allow_direct": false, + "mirror_direct": true, + "sealed": false, + "deny_delete": false, + "deny_purge": false, + "allow_rollup_hdrs": false +} +EOF + +nats -s "nats://_hengliConnUser_:_hengliConnUser_@127.0.0.1:14222" \ + stream add --config origin-stream.json + +nats -s "nats://_hengliConnUser_:_hengliConnUser_@127.0.0.1:14222" \ + stream report + +nats -s "nats://_wswConnUser_:_wswConnUser_@127.0.0.1:24222" \ + stream add --config mirror-stream.json + +nats -s "nats://_wswConnUser_:_wswConnUser_@127.0.0.1:24222" \ + stream report + +echo 'Starting bench...' +nats bench \ + -s "nats://hengli:hengli@127.0.0.1:14222" \ + --pub 1 \ + --js \ + --stream hengli_to_wsw_test \ + --msgs 60000 \ + --no-progress \ + hengli.to.wsw.test + +nats bench \ + -s "nats://hengli:hengli@127.0.0.1:14222" \ + --pub 1 \ + --js \ + --stream hengli_to_wsw_test \ + --msgs 60000 \ + --no-progress \ + hengli.to.wsw.test + +# Report the streams +nats -s "nats://_hengliConnUser_:_hengliConnUser_@127.0.0.1:14222" \ + stream report + +nats -s "nats://_wswConnUser_:_wswConnUser_@127.0.0.1:24222" \ + stream report diff --git a/examples/issues/3724/cli/main.sh_ b/examples/issues/3724/cli/main.sh_ new file mode 100644 index 00000000..2a12de05 --- /dev/null +++ b/examples/issues/3724/cli/main.sh_ @@ -0,0 +1,330 @@ +#!/bin/bash + +set -euo pipefail + +unset NATS_URL + +cat <<- EOF > hub-shared.conf +accounts: { + SYS: { + users: [{user: sys, pass: sys}] + } + APP: { + jetstream: true + users: [{user: app, pass: app}] + } +} + +system_account: SYS +EOF + +# Define the server configs for cluster. +cat <<- EOF > "n1.conf" +server_name: n1 +port: 4222 +http_port: 8222 +include hub-shared.conf +jetstream { + domain: hub + store_dir: "./n1" +} +cluster: { + name: hub + port: 6222 + routes: [ + nats-route://127.0.0.1:6222, + nats-route://127.0.0.1:6223, + nats-route://127.0.0.1:6224, + ] +} +leafnodes { + port: 7422 +} +EOF + +cat <<- EOF > "n2.conf" +server_name: n2 +port: 4223 +include hub-shared.conf +jetstream { + domain: hub + store_dir: "./n2" +} +cluster: { + name: hub + port: 6223 + routes: [ + nats-route://127.0.0.1:6222, + nats-route://127.0.0.1:6223, + nats-route://127.0.0.1:6224, + ] +} +leafnodes { + port: 7423 +} +EOF + +cat <<- EOF > "n3.conf" +server_name: n3 +port: 4224 +include hub-shared.conf +jetstream { + domain: hub + store_dir: "./n3" +} +cluster: { + name: hub + port: 6224 + routes: [ + nats-route://127.0.0.1:6222, + nats-route://127.0.0.1:6223, + nats-route://127.0.0.1:6224, + ] +} +leafnodes { + port: 7424 +} +EOF + +# ### Bring up the cluster + +# Start a server for each configuration and sleep a second in +# between so the seeds can startup and get healthy. +echo "Starting n1..." +nats-server -c n1.conf -P n1.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting n2..." +nats-server -c n2.conf -P n2.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting n3..." +nats-server -c n3.conf -P n3.pid > /dev/null 2>&1 & +sleep 1 + +# Wait until the servers up and healthy. +echo 'Hub cluster healthy?' +curl --fail --silent \ + --retry 5 \ + --retry-delay 1 \ + http://localhost:8222/healthz; echo + +cat <<- EOF > leaf-shared.conf +accounts: { + SYS: { + users: [{user: sys, pass: sys}] + } + APP: { + jetstream: true + users: [{user: app, pass: app}] + } +} + +system_account: SYS + +leafnodes { + remotes [ + { + urls: [ + nats-leaf://app:app@localhost:7422, + nats-leaf://app:app@localhost:7423, + nats-leaf://app:app@localhost:7424, + ] + account: APP + } + ] +} +EOF + + +# Define the server configs for cluster. +cat <<- EOF > "l1.conf" +server_name: l1 +port: 4225 +http_port: 8223 +include leaf-shared.conf +jetstream { + domain: leaf + store_dir: "./l1" +} +cluster: { + name: leaf + port: 6225 + routes: [ + nats-route://127.0.0.1:6225, + nats-route://127.0.0.1:6226, + nats-route://127.0.0.1:6227, + ] +} +EOF + +cat <<- EOF > "l2.conf" +server_name: l2 +port: 4226 +include leaf-shared.conf +jetstream { + domain: leaf + store_dir: "./l2" +} +cluster: { + name: leaf + port: 6226 + routes: [ + nats-route://127.0.0.1:6225, + nats-route://127.0.0.1:6226, + nats-route://127.0.0.1:6227, + ] +} +EOF + +cat <<- EOF > "l3.conf" +server_name: l3 +port: 4227 +include leaf-shared.conf +jetstream { + domain: leaf + store_dir: "./l3" +} +cluster: { + name: leaf + port: 6227 + routes: [ + nats-route://127.0.0.1:6225, + nats-route://127.0.0.1:6226, + nats-route://127.0.0.1:6227, + ] +} +EOF + +# ### Bring up the leaf cluster + +echo "Starting l1..." +nats-server -c l1.conf -P l1.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting l2..." +nats-server -c l2.conf -P l2.pid > /dev/null 2>&1 & +sleep 1 + +echo "Starting l3..." +nats-server -c l3.conf -P l3.pid > /dev/null 2>&1 & +sleep 1 + +# Wait until the servers up and healthy. +echo 'Leaf cluster healthy?' +curl --fail --silent \ + --retry 5 \ + --retry-delay 1 \ + http://localhost:8223/healthz; echo + +nats context save --user app --password app -s nats://localhost:4222 hub-app + +nats context save --user app --password app -s nats://localhost:4225 leaf-app + + +nats context save --user sys --password sys -s nats://localhost:4222 hub-sys + +nats context save --user sys --password sys -s nats://localhost:4225 leaf-sys + +cat <<- EOF > origin.json +{ + "name": "events", + "subjects": [ + "events.*" + ], + "retention": "limits", + "max_consumers": -1, + "max_msgs_per_subject": -1, + "max_msgs": -1, + "max_bytes": -1, + "max_age": 0, + "max_msg_size": -1, + "storage": "file", + "discard": "old", + "num_replicas": 2, + "duplicate_window": 120000000000, + "sealed": false, + "deny_delete": false, + "deny_purge": false, + "allow_rollup_hdrs": false, + "allow_direct": false, + "mirror_direct": false +} +EOF + +cat <<- EOF > hub-mirror.json +{ + "name": "events-m", + "retention": "limits", + "max_consumers": -1, + "max_msgs_per_subject": -1, + "max_msgs": -1, + "max_bytes": -1, + "max_age": 0, + "max_msg_size": -1, + "storage": "file", + "discard": "old", + "num_replicas": 1, + "mirror": { + "name": "events" + }, + "sealed": false, + "deny_delete": false, + "deny_purge": false, + "allow_rollup_hdrs": false, + "allow_direct": false, + "mirror_direct": false +} +EOF + +cat <<- EOF > leaf-mirror.json +{ + "name": "events", + "retention": "limits", + "max_consumers": -1, + "max_msgs_per_subject": -1, + "max_msgs": -1, + "max_bytes": -1, + "max_age": 0, + "max_msg_size": -1, + "storage": "file", + "discard": "old", + "num_replicas": 1, + "mirror": { + "name": "events-m", + "external": { + "api": "\$JS.hub.API" + } + }, + "sealed": false, + "deny_delete": false, + "deny_purge": false, + "allow_rollup_hdrs": false, + "allow_direct": false, + "mirror_direct": false +} +EOF + +nats --context hub-app stream add --config origin.json +nats --context hub-app stream add --config hub-mirror.json +nats --context leaf-app stream add --config leaf-mirror.json + +echo 'Starting bench...' +nats bench \ + --context hub-app \ + --pub 1 \ + --js \ + --size 10k \ + --stream events \ + --msgs 10000 \ + --pubbatch 100 \ + --no-progress \ + --multisubject \ + events + +sleep 2 + +# Report the streams +nats --context hub-app stream report +nats --context leaf-app stream report + diff --git a/examples/messaging/pub-sub/dotnet/Main.cs b/examples/messaging/pub-sub/dotnet/Main.cs new file mode 100644 index 00000000..a850a123 --- /dev/null +++ b/examples/messaging/pub-sub/dotnet/Main.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using NATS.Client; + +// Create a new connection factory to create +// a connection. +Options opts = ConnectionFactory.GetDefaultOptions(); +opts.Url = "nats://nats:4222"; + +// Creates a live connection to the default +// NATS Server running locally +ConnectionFactory cf = new ConnectionFactory(); +IConnection c = cf.CreateConnection(opts); + +// Setup an event handler to process incoming messages. +// An anonymous delegate function is used for brevity. +EventHandler h = (sender, args) => +{ + // print the message + Console.WriteLine(args.Message); + + // Here are some of the accessible properties from + // the message: + // args.Message.Data; + // args.Message.Reply; + // args.Message.Subject; + // args.Message.ArrivalSubcription.Subject; + // args.Message.ArrivalSubcription.QueuedMessageCount; + // args.Message.ArrivalSubcription.Queue; + + // Unsubscribing from within the delegate function is supported. + args.Message.ArrivalSubcription.Unsubscribe(); +}; + +// The simple way to create an asynchronous subscriber +// is to simply pass the event in. Messages will start +// arriving immediately. +IAsyncSubscription s = c.SubscribeAsync("foo", h); + +// Alternatively, create an asynchronous subscriber on subject foo, +// assign a message handler, then start the subscriber. When +// multicasting delegates, this allows all message handlers +// to be setup before messages start arriving. +IAsyncSubscription sAsync = c.SubscribeAsync("foo"); +sAsync.MessageHandler += h; +sAsync.Start(); + +// Simple synchronous subscriber +ISyncSubscription sSync = c.SubscribeSync("foo"); + +// Using a synchronous subscriber, gets the first message available, +// waiting up to 1000 milliseconds (1 second) +Msg m = sSync.NextMessage(1000); + +c.Publish("foo", Encoding.UTF8.GetBytes("hello world")); + +// Unsubscribing +sAsync.Unsubscribe(); + +// Publish requests to the given reply subject: +c.Publish("foo", "bar", Encoding.UTF8.GetBytes("help!")); + +// Sends a request (internally creates an inbox) and Auto-Unsubscribe the +// internal subscriber, which means that the subscriber is unsubscribed +// when receiving the first response from potentially many repliers. +// This call will wait for the reply for up to 1000 milliseconds (1 second). +m = c.Request("foo", Encoding.UTF8.GetBytes("help"), 1000); + +// Draining and closing a connection +c.Drain(); + +// Closing a connection +c.Close();