Skip to content

Commit

Permalink
Update Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
mtmk committed Mar 4, 2024
1 parent eaef1db commit 357c7f6
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 52 deletions.
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ let package = Package(
.executableTarget(name: "Benchmark", dependencies: ["NatsSwift"]),
.executableTarget(name: "BenchmarkPubSub", dependencies: ["NatsSwift"]),
.executableTarget(name: "BenchmarkSub", dependencies: ["NatsSwift"]),
.executableTarget(name: "Example", dependencies: ["NatsSwift"]),
]
)
176 changes: 124 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
<p align="center">
<img src="./Resources/Logo@256.png">
</p>
![NATS Swift Client](./Resources/Logo@256.png)

<p align="center">
A <a href="https://www.swift.org">Swift</a> client for the <a href="https://nats.io">NATS messaging system</a>.
</p>
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Faus-der-Technik%2Fswifty-nats%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/aus-der-Technik/swifty-nats) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Faus-der-Technik%2Fswifty-nats%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/aus-der-Technik/swifty-nats)

**:warning: WARNING: THIS REPOSITORY IS UNDER REWORK AND SHOULD NOT BE USED AT THE MOMENT :warning: **
# NATS Swift Client _(Preview)_

Swift Version Compatibility: [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Faus-der-Technik%2Fswifty-nats%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/aus-der-Technik/swifty-nats)
Platform Compatibility: [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Faus-der-Technik%2Fswifty-nats%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/aus-der-Technik/swifty-nats)
**This version is currently in preview and is not recommended for production use.**

Welcome to the [Swift](https://www.swift.org) Client for [NATS](https://nats.io),
your gateway to asynchronous messaging in Swift applications. This client library
is designed to provide Swift developers with a seamless interface to NATS
messaging, enabling swift and efficient communication across distributed systems.

## Support
Join the [#swift](https://natsio.slack.com/archives/C02D41BU0PQ) channel on nats.io Slack.

Join the [#swift](https://natsio.slack.com/channels/swift) channel on nats.io Slack.
We'll do our best to help quickly. You can also just drop by and say hello. We're looking forward to developing the community.

## Installation via Swift Package Manager
### In Package.swift
Add this packages as a dependency in your projects `Package.swift` file and add the Name to your target like shown in this example:

Include this package as a dependency in your project's `Package.swift` file and add the package name to your target as shown in the following example:

```swift
// swift-tools-version:5.6
// swift-tools-version:5.7

import PackageDescription

Expand All @@ -33,66 +34,137 @@ let package = Package(
.package(name: "NatsSwift", url: "https://github.com/nats-io/NatsSwift.git", from: "0.1")
],
targets: [
.target(
name: "YourApp",
dependencies: ["NatsSwift"]
),
.target(name: "YourApp", dependencies: ["NatsSwift"]),
]
)

```
### In an .xcodeproj
Open the project inspector in XCode and select your project. It is importent to select the **project** and not a target!
Klick on the third tab `Package Dependencies` and add the git url `https://github.com/nats-io/NatsSwift.git` by selecting the litte `+`-sign at the end of the package list.

### Xcode Package Dependencies

Open the project inspector in Xcode and select your project. It is important to select the **project** and not a target!
Click on the third tab `Package Dependencies` and add the git url `https://github.com/nats-io/nats.swift.git` by selecting the little `+`-sign at the end of the package list.

## Basic Usage
```swift

Here is a quick start example to see everything at a glance:

```swift
import NatsSwift

// Setup the logger level
logger.logLevel = .debug
// create the client
let nats = ClientOptions().url(URL(string: "nats://localhost:4222")!).build()

// connect to the server
try await nats.connect()

// subscribe to a subject
let subscription = try await nats.subscribe(to: "events.>")

// create the client
let client = ClientOptions().url(URL(string: natsServer.clientURL)!).build()
// publish a message
try nats.publish("my event".data(using: .utf8)!, subject: "events.example")

// connect to the server
try await client.connect()
// receive published messages
for await msg in subscriptions {
print( "Received: \(String(data:msg.payload!, encoding: .utf8)!)")
}
```

// subscribe to a subject
let subscription = try await client.subscribe(to: "events.>")
### Connecting to a NATS Server

// publish a message
try client.publish("msg".data(using: .utf8)!, subject: "events.example")
The first step is establishing a connection to a NATS server.
This example demonstrates how to connect to a NATS server using the default settings, which assume the server is
running locally on the default port (4222). You can also customize your connection by specifying additional options:

for await message in subscriptions {
print( "payload: \(String(data:message.payload!, encoding: .utf8)!)")
}
```swift
let nats = ClientOptions()
.url(URL(string: "nats://localhost:4222")!)
.build()

try await nats.connect()
```

### Setting the loglevel
The default loglevel is `.error`. You can reset it to see more verbose messages. Possible
Values are `.debug`, `.info`, `.error` or `.critical`
### Publishing Messages

Once you've established a connection to a NATS server, the next step is to publish messages.
Publishing messages to a subject allows any subscribed clients to receive these messages
asynchronously. This example shows how to publish a simple text message to a specific subject.

//FIXME: not a proper way to set a logging level from outside the library
```swift
let client = NatsClient("http://nats.server:4222")
client.config.loglevel = .info
let data = "message text".data(using: .utf8)!
try nats.publish(data, subject: "foo.msg")
```

### List of events
The public class `NatsEvent` contains all events you can subscribt to.
In more complex scenarios, you might want to include additional metadata with your messages in
the form of headers. Headers allow you to pass key-value pairs along with your message, providing
extra context or instructions for the subscriber. This example shows how to publish a
message with headers:

```swift
let data = "message text".data(using: .utf8)!

var headers = HeaderMap()
headers.append(try! HeaderName("X-Example"), HeaderValue("example value"))

try nats.publish(data, subject: "foo.msg.1", headers: headers)
```

| event | description |
| ------------ | ---------------------------------------------------------------------- |
| connected | The client is conected to the server. |
| disconnected | The client disconnects and was connectd before. |
| response | The client gets an response from the server (internal). |
| error | The server sends an error that can't be handled. |
| dropped | The clients droped a message. Mostly because of queue length to short. |
| reconnecting | The client reconencts to the server, (Because of a called reconnect()).|
| informed | The server sends his information data successfully to the client. |
### Subscribing to Subjects

After establishing a connection and publishing messages to a NATS server, the next crucial step is
subscribing to subjects. Subscriptions enable your client to listen for messages published to
specific subjects, facilitating asynchronous communication patterns. This example
will guide you through creating a subscription to a subject, allowing your application to process
incoming messages as they are received.


```swift
let subscription = try await nats.subscribe(to: "foo.>")

for try await msg in subscription {

if msg.subject == "foo.done" {
break
}

if let payload = msg.payload {
print("received \(msg.subject): \(String(data: payload, encoding: .utf8) ?? "")")
}

if let headers = msg.headers {
if let headerValue = headers.get(try! HeaderName("X-Example")) {
print(" header: X-Example: \(headerValue.description)")
}
}
}
```

Notice that the subject `foo.>` uses a special wildcard syntax, allowing for subscription
to a hierarchy of subjects. For more detailed information, please refer to the [NATS documentation
on _Subject-Based Messaging_](https://docs.nats.io/nats-concepts/subjects).

### Setting Log Levels

The default log level is `.info`. You can set it to see more or less verbose messages. Possible values are `.debug`, `.info`, `.error` or `.critical`.

```swift
// TODO
```

### Events

You can also monitor when your app connects, disconnects, or encounters an error using events:

```swift
let nats = ClientOptions()
.url(URL(string: "nats://localhost:4222")!)
.build()

nats.on(.connected) { event in
print("event: connected")
}
```

## Attribution

# Attribution
This library is based on excellent work in https://github.com/aus-der-Technik/NatsSwift
63 changes: 63 additions & 0 deletions Sources/Example/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Foundation
import NatsSwift

print("\n### Setup NATS Connection")

let nats = ClientOptions()
.url(URL(string: "nats://localhost:4222")!)
.build()

nats.on(.connected) { event in
print("event: connected")
}

print("connecting...")
try await nats.connect()

print("\n### Publish / Subscribe")

print("subscribing...")
let sub = try await nats.subscribe(to: "foo.>")

let loop = Task {
print("starting message loop...")

for try await msg in sub {

if msg.subject == "foo.done" {
break
}

if let payload = msg.payload {
print("received \(msg.subject): \(String(data: payload, encoding: .utf8) ?? "")")
}

if let headers = msg.headers {
if let headerValue = headers.get(try! HeaderName("X-Example")) {
print(" header: X-Example: \(headerValue.description)")
}
}
}

print("message loop done...")
}

print("publishing data...")
for i in 1...3 {
var headers = HeaderMap()
headers.append(try! HeaderName("X-Example"), HeaderValue("example value"))

if let data = "data\(i)".data(using: .utf8) {
try nats.publish(data, subject: "foo.\(i)", headers: headers)
}
}

print("signalling done...")
try nats.publish(Data(), subject: "foo.done")

try await loop.value

print("closing...")
try await nats.close()

print("bye")

0 comments on commit 357c7f6

Please sign in to comment.