Love, functional programming, Node.js, Lua and Redis.

Kyle
3 min readAug 28, 2015

--

This is part 14 of my Node / Redis series. The previous part was Tick-tock: setting a timeout on a Redis call with Node.js.

I’ve recently fallen in love with functional programming. No need to tell my wife though — it’s an imperfect relationship… err, with functional programming, not the wife. My relationship with my wife is just peachy. Functional programming and I keep having spats about side effects. Functional programming keeps saying that I shouldn’t have side effects, but I just can’t stop using Redis.

On the other hand, functional programming is so… beautiful. I’m not sure I can achieve any sort of functional purity in my day-to-day programming but I think I can import some of that functional beauty into my code. That’s my aim — beautiful, functional-like code that harnesses the power of Redis.

Dipping your toe into functional programming usually starts with map. It’s such an easy concept to get. Take each element of an array and do something with it. Return each new value back into a new array. Easy-peasy.

But what about Redis? Let’s say you have an array of Redis keys and you want all the values returned back into the array. We’ll call this redisKeyMap. The first problem you run into with this is that you need to know what type is stored at that key. While you could easily run a TYPE command that’s a lot of back-and-forth. Let’s right a little Lua script that you can pass a single key to and get back the value of that key, regardless of the type.

This little script just calls TYPE on the passed key, determines what command would be best to grab the data and returns three values — the key, the key type and the value. One aside regarding this script — I ran into a wall initially — I had everything the same except line 1 looked like this:

local keyType = redis.call(“type”, KEYS[1])

Spot the difference? The working version (in the Gist) has [“ok”] at the end. Evidently, TYPE doesn’t return a Lua string, but rather a Lua table with the status (“ok”) and the type.

How I feel when I figure out something in Redis Lua

Obviously, these commands won’t be ideal for every set of data — returning a full list, set or zset could mean millions of items for your data. Just keep that in mind.

So, back to Node. Let’s load this Lua script into EVAL and write a nice little function to run it efficiently. We’ll use a multi object and with a forEach statement.

I’m trying, Eric! Gotta go through both side effects and a forEach to get to a reasonable map-like function.

After we send those commands out to Redis, we’ll make sense of the returned values. The exec callback with node_redis returns an array for each command passed. Looking at the Lua that we wrote, each array item itself will be an array of three items — the key, the type and the values. We’ll map those values and return it back to our callback.

So, if you run this you’ll get back something like this:

[{ key: ‘a-hash’, keyType: ‘hash’, value: [ ‘field’, ‘value’, ... ] },
{ key: ‘a-list’, keyType: ‘list’, value: [ ‘list-item’, ... ] },
{ key: ‘a-set’, keyType: ‘set’, value: [ ‘set-member’, ...] },
{ key: ‘a-string’, keyType: ‘string’, value: ‘string value’ },
{ key: ‘a-zset’, keyType: ‘zset’, value: [ ‘zset item with score’, ‘1’, ... ] }]

You’ve now got a flexible way to grab the value for any key(s) that you can throw at it. But wait…there’s more. If you use async, you could manipulate each value and write it back to Redis. Oh the possibilities.

--

--

Kyle

Developer of things. Node.js + all the frontend jazz. Also, not from Stockholm, don’t do UX. Long story.