Read this, Read that, Redis.

Noze.io is starting to get persistent. Publish “Hi!” to Redis.

Starting with Noze.io 0.3 a Redis client is included. Redis is a very fast, scalable and easy to use key-value store. One common usecase is to store connect sessions in Redis, but it can be used for all kinds of applications. Checkout the Redis website to learn more about it.

The Noze.io implementation is a clean-room, Noze.io specific Redis implementation. As usual it is fully asynchronous, non-blocking and ßatch based.

Noze.io Redis Client

So how does that look in Noze.io? We took inspiration by the node-redis module and modeled the Noze.io version after that. The result looks almost exactly the same, except that you get an AOT compiled, statically type-checked binary. It is also a great demo on how static typing rarely helps to avoid real-world bugs 🤓

OK, lets jump in - Connect to Redis, store a key and retrieve it afterwards:

import redis

let client = redis.createClient()

client.set("message_of_the_day", "Hello World", redis.print)
client.get("message_of_the_day") { err, reply in
  console.log("Reply: ", reply)
}

Note redis.print. This is a function which can be used as a callback for debugging/testing purposes. It just logs the err/reply coming back.

Redis can store simple key/value pairs, but it can also store more complex stuff as lists, sets or hashes. A demo for the latter (essentially [String:String] dictionaries) is contained in our todo-mvc-redis.

Another feature Redis provides alongside KVS is a Pub/Sub broker. Think “Slack” or “IRC”. Your client subscribes to some channels and gets notified when messages get published on those channels. Sample:

let sub = redis.createClient(), pub = redis.createClient()

sub.onSubscribe { channel, count in
  pub.publish("io.noze.random", "Hey guys!")
  pub.publish("io.noze.random", "What is the reldate for Noze.io 6.3.2?")
}

sub.onMessage { channel, message in
  console.log("#\(channel): ", message)
}

sub.subscribe("io.noze.random")

You get the idea.

New Example: todo-mvc-redis

To give a more complete example we added todo-mvc-redis. It is a sample Todo-Backend which persists the todos as Redis hashes and uses Redis INCR to maintain a primary key sequence.

Check it out! It actually works :-)

Changes in 0.3.0 (from 0.2.11)

  • new module: redis
    • This is a pure Swift, clean-room Noze.io specific Redis client. Fully asynchronous and non-blocking. And quite likely full of bugs :-)
    • Alongside: new example todo-mvc-redis
      • todo-mvc-redis is a sample Todo-Backend which persists the todos as Redis hashes
  • global changes
    • All code has been converted to use Swift 3 style types and methods. That is, ErrorProtocol instead of ErrorType, Sequence instead of SequenceType and so on. Also: Most code is now using Swift 3 style collection APIs, like remove(at:) instead of removeAtIndex() or append(contentsOf:) instead of appendContentsOf(). The necessary compatibility aliases are contained in the core module. So just import that and you are Swift 3-stylish.
    • All code has been converted from dispatch_async(Q) to the new Q.async() “Objective-GCD” API
    • Various workarounds to please Swift 3.0 Preview 2, e.g. use sizeof(T.self) instead of sizeof(T).
  • xsys module
    • Added some support for timeval_t
    • Added timeval_any protocol which enhances three Unix time value types (timespec_t, timeval_t, time_t) with common functionality (like let now = timeval_t.now)
    • Added a tiny testsuite
    • Added support for uuid_generate and companions. Unfortunately this is not part of Glibc and hence only available on Darwin. (Linux has this in a separate library, libuuid)
  • core module
    • Enhance Swift 2 to support required Swift 3 style types and methods
    • Changed CIDictionary to be more Swift 3 style
    • Added a debug facility to track core.retain/release calls to debug retain counting issues. Core.retain is used to keep the process alive while async code is running.
  • events module
    • onError is marked @discardableResult on Swift 3 now, but that just produces a follow-up compiler warning
  • streams module
    • mark some internal stuff as public to please the Linux linker when using generic classes (might be a bug, we’ll see how it looks in Swift 3 final)
  • fs module
    • Fixed bug in tracking the number of active read and writes
  • console module
    • The secondary arguments to the various console functions (log, warn etc.) now take Any value (was CustomStringConvertible before). This means you can now do such: console.log("stream: ", stream).
  • dns module
    • The callback signature has changed to a proper (err,address) from (address,err)
    • Changed the family argument of lookup from Int32 to sa_family_t. Node uses just 4 and 6 values to specify IPv4/IPv6, we essentially allow any valid PF_ value.
  • net module
    • The connect options gained a family property which defaults to IPv4. Previously it just used the first match dns.lookup returned, which sometimes is IPv4 and sometimes IPv6. Now you can specify your desired family.
    • A specific SocketError enum was added (was using POSIXError before)
  • process module
    • Swift 3: Internal change: processInfo is now a property
  • child_process module
    • Some bitz of error printing/asserts. Sometimes this seems to have issues.
  • json module
    • Provided Swift 3 “kw-less” wrapper. That is, you can now call stringify(obj) instead of stringfy(object: obj).
  • connect module
    • The signature of the next callback of middleware functions changed from (String)->Void to (Any)->Void. In preparation of support for error middleware.
    • Added the connect.pause middleware. This is just used to simulate latency, i.e. you can slow down request handling.

A word about Swift 3.0 Preview 2

Noze.io builds against Swift 3.0 Preview 2 on macOS. It does build against Swift 3.0 Preview 2 on the Linux Travis CI is running, so it should work.

However: We didn’t yet get a libdispatch version running against Swift 3pr2 on an own Linux instance. So you may need to stick to Swift 3 Preview 1 on Linux if you really want to use Swift 3 already.

Our recommendation is still the same: Stay with Swift 2.2/2.3 until Swift 3 - particularily Swift 3 libdispatch on Linux - is sufficiently stable.

Getting the stuff

Well, as usual, head over to GitHub and checkout the master branch or fetch the 0.3.0 tag. Happz noziredizing!

hh

Written on July 25, 2016