Yet another TODO app! With Redis and Go [Part 1]
Tags: redis, go, showdev, azure
Published: 2020-04-06 15:10:40

[Redis](https://redis.io/) is a versatile key value that supports a variety of [rich data structures](https://redis.io/commands/) such as `List`, `Set`, `Sorted Set`, `Hash` etc. - this means that values can be more than just a simple `string`. These data structures when combined, can be used to build powerful applications for use-cases ranging from caching (which is bread and butter for Redis), real-time processing, distributed work queues, leaderboards, session store, etc.

This *two-part blog series* will cover some of the Redis data structures with the help of a simple yet practical example: *another* **TODO app**! 😉 Instead of building a web-based front end interface (which is really not my cup of tea, to be honest!) I chose to keep it simple and provide a command-line interface (CLI). It is built in [`Go`](https://golang.org/) with the popular [`cobra`](https://github.com/spf13/cobra) library for CLI apps and uses `Redis` as the backend store.

![](https://media.giphy.com/media/3oz8xQQP4ahKiyuxHy/giphy-downsized.gif)

As you go through this series, you will learn about:

- Common `Redis` data structures - this application makes use of `HASH` and `SET`
- Interacting with Redis using the [`go-redis`](https://github.com/go-redis/redis) client
- How to use the `cobra` library (which also powers CLI tools like `docker`, `kubectl` etc.)
- You can try out the `todo` app with a couple of different `Redis` options: `Docker` or [Azure Redis Cache](https://docs.microsoft.com/azure/azure-cache-for-redis/?WT.mc_id=devto-blog-abhishgu)

I have split it up into two parts to keep things simple. Part one (this blog) will provide a quick overview of the app, installation, and setup (including `Azure Redis Cache`) and try it out. The second part will dive into the code and implementation details

> The code is [available on Github](https://github.com/abhirockzz/redis-todo-cli-app)

## Overview of the `todo` app

Here is a quick overview of what you can do with the `todo` CLI app. It's easy to figure this out using `todo --help`: the output is self-explanatory:

```
Yet another TODO app. Uses Go and Redis

Usage:
  todo [command]

Available Commands:
  create      create a todo with description
  delete      delete a todo
  help        Help about any command
  list        list all todos
  update      update todo description, status or both

Flags:
  -h, --help      help for todo
  -v, --version   version for todo

Use "todo [command] --help" for more information about a command.
```

You can `create`, `list`, `update` and `delete` todos (good old CRUD!)

- To `create` a `todo`, simply enter the `description` - for details, use `todo create --help`
- To `list` all the todos, simply use `todo list`. It's also possible to filter by `status` (completed or pending) - for details, use `todo list --help`

Here is an output from `todo list`:

```
+----+--------------------------------+-------------+
| ID |          DESCRIPTION           |   STATUS    |
+----+--------------------------------+-------------+
|  3 | push redis todo cli app code   | pending     |
|    | to github                      |             |
|  2 | write tutorial for redis todo  | in-progress |
|    | cli app                        |             |
|  1 | implement todo cli app         | completed   |
+----+--------------------------------+-------------+
```

- You can `update` the `description`, `status` (or both) for a `todo` by specifying the todo `id` - for details, use `todo update --help`
- To `delete` a todo, just use `todo delete` along with it's `id` - for details, use `todo delete --help`

## `todo` app installation

> I am assuming you have [`Go`](https://golang.org/) installed

Start by cloning the repo:

```
git clone https://github.com/abhirockzz/redis-todo-cli-app
cd redis-todo-cli-app
```

Build the app and set the `PATH` variable

```
go build -o todo
export PATH=$(pwd):$PATH
```

To confirm, use `todo --help`

Before using the app, set up a Redis instance

## Redis setup

The `todo`s are stored in `Redis`. One of the quickest ways get a `Redis` instance is to just pull it's Docker image and start using it:

```
docker pull redis
docker run -d --name todo_redis -p 6379:6379 redis
```

You should now have Redis Docker container running in the background and to should be accessible on port `6379`

> To delete the container (not the image), simply use `docker rm -f todo_redis`

If you're using the Docker based setup, you can skip the rest and head to the next (final) section since the app uses `localhost:6379` as default Redis host

If you already want to override this, simply set the `REDIS_HOST` environment variable, e.g. 

```
export REDIS_HOST=myredis:6379
```

If your Redis instance is password protected, just set the `REDIS_PASSWORD_REQUIRED` environment variable to `true` and use `REDIS_PASSWORD` environment variable to specify the password, e.g.

```
export REDIS_HOST=my-secure-redis:6379
export REDIS_PASSWORD_REQUIRED=true
export REDIS_PASSWORD=foobarredis
```

### Azure Redis Cache

[Azure Cache for Redis is a managed offering in the cloud](https://docs.microsoft.com/azure/azure-cache-for-redis/cache-overview?WT.mc_id=devto-blog-abhishgu). It provides access to a secure, dedicated Redis cache which is hosted within Azure, and accessible to any application within or outside of Azure. 

For the purposes of this blog, we will setup an Azure Redis Cache with a `Basic` tier which is a single node cache ideal for development/test and non-critical workloads. Please note that you also choose from `Standard` and `Premium` tiers which [provide different features ranging from persistence, clustering, geo-replication etc](https://docs.microsoft.com/azure/azure-cache-for-redis/cache-overview?WT.mc_id=devto-blog-abhishgu#feature-comparison).

You can use the Azure CLI to quickly setup an Azure Redis Cache instance with the [`az redis create`](https://docs.microsoft.com/cli/azure/redis?view=azure-cli-latest&WT.mc_id=devto-blog-abhishgu#az-redis-create) command, e.g.

```
az redis create --location westus2 --name todo-redis --resource-group todo-app-group --sku Basic --vm-size c0
```

> Checkout ["Create an Azure Cache for Redis"](https://docs.microsoft.com/azure/azure-cache-for-redis/scripts/create-cache?WT.mc_id=devto-blog-abhishgu) for a step-by-step guide

Once that's done, you need the get the information required to connect to Azure Redis Cache instance i.e. host, port and access keys. This can be done using CLI as well, e.g.

```
//host and (SSL) port
az redis show --name todo-redis --resource-group todo-app-group --query [hostName,sslPort] --output tsv

//primary access key
az redis list-keys --name todo-redis --resource-group todo-app-group --query [primaryKey] --output tsv
```

> Checkout ["Get the hostname, ports, and keys for Azure Cache for Redis"](https://docs.microsoft.com/azure/azure-cache-for-redis/scripts/cache-keys-ports?WT.mc_id=devto-blog-abhishgu) for a step-by-step guide

Alright, now you can set the required environment variables with the info you just extracted, e.g.

```
//todo-redis is the name of the cache
export REDIS_HOST=todo-redis.redis.cache.windows.net:6380
export REDIS_PASSWORD_REQUIRED=true
export REDIS_PASSWORD=[primary access key]
export REDIS_SSL_REQUIRED=true
```



> The application uses TLS 1.2 to connect to Redis over SSL - [this is the recommended approach](https://docs.microsoft.com/azure/azure-cache-for-redis/cache-remove-tls-10-11?WT.mc_id=devto-blog-abhishgu)

You should be all set to try the app

## `CRUD` some todos!

Start by creating a `todo`

```
todo create --description "write the todo cli app"
```

You should see this response

```
created todo! use 'todo list' to get your todos
```

Create a few more

```
todo create --description "write the tutorial for redis cli app using go"
todo create --description "push cli app code to github"
todo create --description "get some sleep"
```

List all your `todo`s with `todo list`. You should see:

```
+----+--------------------------------+---------+
| ID |          DESCRIPTION           | STATUS  |
+----+--------------------------------+---------+
|  3 | push cli app code to github    | pending |
|  2 | write the tutorial for redis   | pending |
|    | cli app using go               |         |
|  1 | write the todo cli app         | pending |
|  4 | get some sleep                 | pending |
+----+--------------------------------+---------+
```

Update a few `todo`s

```
todo update --id 1 --status completed
todo update --id 2 --status in-progress
todo update --id 4 --description "get some sleep NOW"
```

Listing the `todo`s should give you the updated info:

```
+----+--------------------------------+-------------+
| ID |          DESCRIPTION           |   STATUS    |
+----+--------------------------------+-------------+
|  3 | push cli app code to github    | pending     |
|  2 | write the tutorial for redis   | in-progress |
|    | cli app using go               |             |
|  1 | write the todo cli app         | completed   |
|  4 | get some sleep NOW             | pending     |
+----+--------------------------------+-------------+
```

List `pending` `todo`s only: 

```
todo list --status pending
```

You should get:

```
+----+-----------------------------+---------+
| ID |         DESCRIPTION         | STATUS  |
+----+-----------------------------+---------+
|  3 | push cli app code to github | pending |
|  4 | get some sleep NOW          | pending |
+----+-----------------------------+---------+
```

Let's delete `todo` #4 (who needs sleep!?)

```
todo delete --id 4
```

No more sleep required! (as per `todo list`)

```
+----+--------------------------------+-------------+
| ID |          DESCRIPTION           |   STATUS    |
+----+--------------------------------+-------------+
|  3 | push cli app code to github    | pending     |
|  2 | write the tutorial for redis   | in-progress |
|    | cli app using go               |             |
|  1 | write the todo cli app         | completed   |
+----+--------------------------------+-------------+
```

### Double check Redis

Let's confirm by peeking into the Redis data structures. You can use the [`redis-cli`](https://redis.io/topics/rediscli) for this. If you're using the Azure Redis Cache, I would recommend using a really handy [web based Redis console](https://docs.microsoft.com/azure/azure-cache-for-redis/cache-configure?WT.mc_id=devto-blog-abhishgu#redis-console) for this

Let's check the data structures which have been created. We use `todo` to name the data structures (implementation details in the next blog post), so we can use [`SCAN`](https://redis.io/commands/scan) using this pattern

```
SCAN 0 COUNT 1000 MATCH todo*
```

> the [`KEYS`](https://redis.io/commands/keys) command is prohibited to due to performance concerns

You will see the following output:

```
1) "0"
2) 1) "todos-id-set"
   2) "todo:1"
   3) "todo:2"
   4) "todo:3"
   5) "todoid"
```

`todos-id-set` and `todoid` correspond to `SET` and `STRING` (counter) data types respectively. `todo:1`, `todo:2` and `todo:3` are the `HASH` data types which contain the `todo` details. Let's look at `todo:1` (i.e. `todo` with `id` 1)

```
HGETALL todo:1
```

You should get the following response:

```
1) "status"
2) "pending"
3) "desc"
4) "write the todo cli app"
```

> As an excercise, confirm the other `todo`s and also peek into the `SET` and `STRING` counter data types

Alright! That concludes this blog post. Stay tuned for the second part, where we will explore the code and see how things work.