Recent Posts

Introducing the Aino framework

Posted on 16 Sep 2021

For the last few weeks I’ve been playing around with a new HTTP framework I’m calling Aino. See it on GitHub.

Aino is built on top of Elli and loosely based around Ring from Clojure. It doesn’t use Plug or Phoenix, though I’m sure some concepts were pulled from it given that’s my day job!

Why make a new framework? What are Aino’s goals?

Aino is an experiment to try out a new way of writing HTTP applications on Elixir. It uses elli instead of Cowboy like Phoenix and Plug. I wanted to see if there were different ways of writing web apps in Elixir. Is there a better way than MVC? Is there a better view layer? What would happen if we try a different HTTP library? Is there a better router? These are the sorts of questions I wanted to play around with.

With the current trajectory of Phoenix, I’ve been thinking a lot on how to keep “dead views” still alive. I personally think they have a seat at the table. I have listened to several mentors of mine from REST Fest talk about how we shouldn’t keep state on the server for web/API clients. It’s conversations and lessons like these that are guiding me towards exploring something like Aino.

Aino will likely stay as a very fast server side renderer and API framework. I have ideas on what to do for websockets if I ever need or want to add them in, elli has the capability through another library. These ideas come from a lot of experimenting in Grapevine and Kalevala with cowboy websockets directly, so that’s my general plan if I end up there.

Why the name Aino?

Aino is a character in the Kalevala. She’s also the wife of Jean Sibelius, a composer that wrote works involving the Kalevala.

It’s loosely themed around my other project Kalevala, a text world builder. Plus my wife picked the name.

What makes up Aino?

Aino is built around a handler. The handler receives a token for the request and then reduces over a list of middleware to generate a response. Tokens are simple maps with no defined structure, middleware are functions that take a single argument of the token.

Aino ships with a handful of common middleware, including parsing request POST body of a few MIME types (url encoded and JSON at the moment), header parsing, a tiny view wrapper around EEx, a very simple router, and simple session stored in cookies.

The Aino.Token is taken from René Föhring’s excellent blog post and ElixirConf 2018 talk. I went with a simple map instead of a struct because this enables anyone to add any key in middleware without needing to extend a token struct. Using a simple map was also fits more in line with what Ring uses for passing data between middleware.

Example

If you want to see a more realistic example, I’ve written an RSS reader using Aino and it turned out well. You can view the source here on GitHub.

Below is a simple example of Aino using most of it’s pieces to render “Hello, World”.

defmodule AinoExample.Application do
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    children = [
      {Aino, callback: AinoExample.Handler, port: 3000}
    ]

    opts = [strategy: :one_for_one, name: AinoExample.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

defmodule AinoExample.Handler do
  @behaviour Aino.Handler

  import Aino.Middleware.Routes, only: [get: 2]

  @impl true
  def handle(token) do
    routes = [
      get("/", &AinoExample.Pages.index/1)
    ]

    middleware = [
      Aino.Middleware.common(),
      &Aino.Middleware.Routes.routes(&1, routes),
      &Aino.Middleware.Routes.match_route/1,
      &Aino.Middleware.params/1,
      &Aino.Middleware.Routes.handle_route/1,
    ]

    Aino.Token.reduce(token, middleware)
  end
end

defmodule AinoExample.Pages do
  alias Aino.Token

  def index(token) do
    token
    |> Token.response_status(200)
    |> Token.response_header("Content-Type", "text/plain")
    |> Token.response_body("Hello, world!\n")
  end
end

Aino doesn’t do a lot for you at the moment, and I’m not sure how much I want to abstract it away. I like the raw internals of HTTP right in your face. I have a few helper functions around redirecting and rendering HTML, so this will probably be the path forward for making things easier to use.

Benchmarks

For initial benchmarks I was slightly blown away. Aino is only a few hundreds of lines of code, so being this fast makes sense. It’s not doing a lot of work for you.

My benchmark script looks like this. It’s running against the example above and a Phoenix application that was generated fresh, a single new route of “/hello” that points at the following controller, and generated via MIX_ENV=prod mix release.

I am including Phoenix as a point of comparison, I have not done Phoenix performance tweaking before so it might be able to get higher with more tweaks.

defmodule HelloWeb.HelloController do
  use HelloWeb, :controller

  def index(conn, _params) do
    send_resp(conn, 200, "Hello, world!")
  end
end
defmodule Bench do
  def test_aino() do
    Finch.build(:get, "http://localhost:3000/") |> Finch.request(Bench)
  end

  def test_phoenix() do
    Finch.build(:get, "http://localhost:4001/hello") |> Finch.request(Bench)
  end
end

{:ok, _pid} = Finch.start_link(name: Bench)
Benchee.run(%{
  "aino" => &Bench.test_aino/0,
  "phoenix" => &Bench.test_phoenix/0
}, time: 10)
❯ mix run bench.exs
Operating System: Linux
CPU Information: AMD Ryzen Threadripper 3970X 32-Core Processor
Number of Available Cores: 64
Available memory: 125.65 GB
Elixir 1.12.2
Erlang 24.0.5

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 10 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 24 s

Benchmarking aino...
Benchmarking phoenix...

Name              ips        average  deviation         median         99th %
aino          12.21 K       81.88 μs    ±15.48%       79.82 μs      100.68 μs
phoenix        5.46 K      183.26 μs    ±10.87%      179.69 μs      297.52 μs

Comparison: 
aino          12.21 K
phoenix        5.46 K - 2.24x slower +101.38 μs

I’m very surprised at how well Aino / mostly Elli does in terms of rendering simple data. The results are encouraging enough that I’ve kept working on Aino.

Current State

Aino is currently at an MVP stage, it works well enough to write simple applications. It’s partially tested and mostly documented. There are a handful of pieces that still need better testing, and likely better documentation.

The last week or so I’ve mostly worked on documenting everything about Aino, and getting it set up to auto deploy documentation to a website before it’s uploaded to hex. I now have ainoweb.dev set up to build documentation on every git push so it’ll always be up to date!

Please give the docs a look over and I’m more than happy to hear any feedback.

Grapevine Updates for November 2019

Posted on 30 Nov 2019

The last month of Grapevine continued background “unseen” changes. The big deal for this month was splitting off the socket code to its own Erlang node. This lets me redeploy the website without taking down the chat socket.

I also rebranded the Patreon to be aimed at myself vs any of the individual projects. I think this makes sense going forward since I have a handful of projects all in the MUD space but separate as entities; Grapevine, ExVenture, and Titans of Text. The new patreon is at patreon.com/ericoestrich.

Links for ExVenture & Grapevine:

New Socket Node

The main new big feature is the web chat socket is now living on its own Erlang node. What this means is when I deploy the website, the socket won’t have to go down. This means chat should get disconnected much less often. It will still go down if I need to deploy the socket code, but that will be much less than the website.

Some day I might get adventurous enough to get hot code loading working so it never goes down. To get here, let’s make Grapevine hoppin’.

Spam Users

Grapevine for a while has been getting some spam accounts being created, which hasn’t been that bad but after a few months the users have finally gotten to the point where I needed to do something about it. Mostly to prevent my mail reputation from going down the drain.

To prevent spam going forward I added recaptcha to the sign up. This is just the simple “I am not a robot” checkmark. I also cleared out any account that looked like a spam account from my unverified email list. I hopefully didn’t delete anyone’s real account, but clearing out 30+ pages of fake emails is a mind numbing thing.

New Games

We have a new set of games showing up on the chat, Schism from ChatMUD made a MOO client for chatting so a few more MOOs have shown up and the chat is active (finally!)

It seems like Grapevine is starting to reach a critical mass of games and players to be active throughout the day. Which is really exciting.

Decanter

I’m still moving on getting Decanter set up but since I was fairly busy last month prepping for a conference talk (a keynote for The Big Elixir) it got side tracked. I’m hoping we can have this ready to go by the start of next year.

For those who don’t know Decanter is going to be a place to post game news and updates. Think a gaming news site but specifically for us.

Social Updates

We have a few new patrons this month, welcome! Thanks for supporting both ExVenture and Grapevine. If you would like to support both projects, check out the Patreon.

Titans of Text has had a lot of episodes come out. If you’re in the MUD community and want to be on an episode, reach out to us! We want to have you on.

Early this month I gave one of the keynotes for The Big Elixir. The video of this should be up soon. I think it went very well and I got to show off how Grapevine and ExVenture worked internally. I will also be giving this talk at Lonestar Elixir in February, maybe I’ll see you there!

Next Month

I was previously going to swing back around to the web client, but now that the chat is being used I might work on some admin tools for that. They’re sorely lacking at the moment. I also noticed a lot of you all trying to use emotes and complaining that they didn’t work well 😃, so figuring something out for that will be good.

Grapevine Updates for October 2019

Posted on 31 Oct 2019

The last month of Grapevine has started work on a new part of Grapevine we’re calling Decanter. This will be a place to share news about all things text.

I am also giving one of the keynotes for The Big Elixir next week and have been working hard on that. I hope to see you there (or maybe on YouTube when it’s uploaded!)

If you’re new please check out the ExVenture & Grapevine Patreon page and consider supporting to help pay for servers or get your own hosted instance of ExVenture!

Links for ExVenture & Grapevine:

Decanter

Decanter is a new part of Grapevine that will let you publish news about your game into a centralized place. Think of it as a new gaming news site that only covers text games, the best kind of games.

It’s still under construction so it’s hard to show what it looks like yet. I haven’t really gotten the styles in place for it to be public. But if you’re extra curious, you can download the latest Grapevine code and check it out locally.

The plan is for anyone to submit a news article, and one of our editors will review it and publish the post. Posts are done in markdown and you can preview before submitting them. I still need to let you optionally attach your game to a post. If you attach your game I’ll be able to display it nicely so people know what they’re reading about.

We’re hoping that this leads to a better landing page for news and updates than say /r/MUD. This works well, but I think we can deliver a much better landing spot for people new to MUDs and looking to learn more and see what’s out there.

Hacktoberfest

Grapevine was part of Hacktoberfest this year and I got a lot of great submissions! I was happy to see new people (or people at all!) submitting PRs and enhancing Grapevine.

Some of those include:

  • An updated settings sidebar which lists all of your games, removing the table of them
  • Analytics for events, so admins can see how many times they’re viewed
  • Generating a session token for the web client for mobile app usage
  • Documentation updates and fixing broken seeds

Thanks again to everyone who submited a PR during October!

Small Updates

  • The HCL parser was renamed to UCL
  • UCL parses comments now

Social

We have a few new patrons this month, welcome! Thanks for supporting both ExVenture and Grapevine. If you would like to support both projects, check out the Patreon.

Titans of Text has had a lot of episodes come out. If you’re in the MUD community and want to be on an episode, reach out to us! We want to have you on.

Once again, I’ll be at The Big Elixir next week giving the keynote on Friday. I’ll be talking about moving from an entirely stateless application to a stateful application using ExVenture and Grapevine as examples of you can achieve that. I think it’s turning out to be pretty good so I hope to see you there.

Next Month

For next month, I’m hoping to wrap up the MVP of decanter and it loose on the world. I may also play around with some web client stuff again or actually get back into ExVenture. I’ve been having a lot of fun extending MidMUD for NaMuBuMo and it’s made me feel nostalgic for working on ExVenture again.

Grapevine Updates for September 2019

Posted on 30 Sep 2019

The last month of Grapevine has picked up pace, I’ve been working through a lot of little things here and there to get back into the development groove.

If you’re new please check out the ExVenture & Grapevine Patreon page and consider supporting to help pay for servers or get your own hosted instance of ExVenture!

Links for ExVenture & Grapevine:

Mobile Client

I started on a mobile client for Grapevine. This uses react native and connects similarly as the web client. This means it will proxy everything through my servers. I am going to head this route because it will be significantly less development to have a web client and a mobile client going if they use the same telnet backing code.

I haven’t spent a ton of time of it yet, but after a few hours I have it connecting, displaying, and sending text to a real game. It’s pretty encouraging.

Grapevine's mobile client

Hosted Sites

I spent a bit of time working on the settings for a hosted site. I mostly wanted to figure out how to allow for safe markdown display based on input from anyone. I got this working by finding a library that will strip text down to only markdown allowed tags.

See Spigot’s hosted site.

Spigot's hosted site

IO Lists

After ElixirConf this year I switched Spigot to using IO lists instead of strings. This got a pretty great speed boost, which you can read more about on the SmartLogic Blog.

Small Tweaks

  • Receive an alert anytime your game has a failed scrape
  • Admin panel for channels
  • Fix bug when creating a new game and adding an image
  • gossip-elixir is on latest telemetry
  • API for the games page
  • Record timestamp of activity through the web client
  • Social fields on a game
  • Generic events
  • List current events on the homepage
  • Display the play button even when signed out
  • Rate limit channel sends

Social

We have a few new patrons this month, welcome! Thanks for supporting both ExVenture and Grapevine. If you would like to support both projects, check out the Patreon.

Titans of Text has had a lot of episodes come out. If you’re in the MUD community and want to be on an episode, reach out to us! We want to have you on.

Next Months

Next month is NaMuBuMo, so I will hopefully be working on a world for that. I’ve been playing around with a file based format for running a game, as a twist to ExVenture. We’ll see if it sticks, but I like where it’s headed.

Grapevine Updates for June - August 2019

Posted on 28 Aug 2019

The last few months of Grapevine has been fairly slow, but I’m getting back around in the swing of things and finally feel like I have enough small things to talk about in an update post!

If you’re new please check out the ExVenture & Grapevine Patreon page and consider supporting to help pay for servers or get your own hosted instance of ExVenture!

Links for ExVenture & Grapevine:

New Game Stats

The most recent additions are new statistics for games that have MSSP or are connected to the web socket. There are three new graphs: the last 48 hours with min/max/average, the last 7 days of player counts, and the last 7 days broken up into hour of day to show the min/max/average of connected users per hour.

These are pretty neat to see with real statistics. You can see player count fluxuate as they come and go during the day and night. I’m looking at adding more historical data as well, but there is only ~8 months of data on the server so there isn’t a huge use right now until more data builds up.

Below is a screen shot of the later two charts:

Grapevine game statistics

New Web Chat Client

During June, I updated the web chat client to not suck. I’m pretty sure it was broken sometime after the merge of Gossip and Grapevine and no one noticed, me included. It is now much nicer, and looks very similar to the web client for playing games.

This merges the tab interface previously in place, to show a single stream across all channels, which is fairly similar to what you’d be expecting in a game connection. You can see which channel you’re chatting in with the select box next to the text area. You can swap channels by doing using a slash command to prefix your message (e.g. /gossip hello, to switch to the gossip channel and say hello.)

Grapevine web chat

Small Tweaks

  • Discord link for game profiles
  • Breaking apart the data layer into a separate application
  • Records chat messages for reply in the web chat
  • Connect/disconnect buttons in the web client
  • Hide players in the socket connection
  • Nicer error for web client is enabled for signed in users only
  • Save web client sessions for viewing length in the admin

Social

We have a few new patrons this month, welcome! Thanks for supporting both ExVenture and Grapevine. If you would like to support both projects, check out the Patreon.

Titans of Text has had a lot of episodes come out. If you’re in the MUD community and want to be on an episode, reach out to us! We want to have you on.

Next Months

I’m still starting to slowly get back into growing Grapevine again and I don’t want to jump too deep back into it to completely burn out. So I’ll most likely keep doing small tasks and possibly work on some clustering stuff from before as that’s pretty exciting.

Creative Commons License
This site's content is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License unless otherwise specified. Code on this site is licensed under the MIT License unless otherwise specified.