Entry tags:
Library review: Cowboy, Sumo Rest
The other end of the Erlang experiment is the libraries I was working with. My application was built on the Sumo Rest stack, built on top of the Erlang Cowboy HTTP server.
I found this finicky and prone to vague runtime errors. That's not important, though. The overall style of the system was pretty reasonable, and is probably a good way to write REST services in general.
Erlang's fundamental unit of code is a module, corresponding to a single source file. A module can implement a behaviour (always with British spelling), which is a set of required functions (in other words, an "interface" in Java- or Go-speak). You can pass an atom that is a module's name into apply/3 to dynamically call functions (and there might even be a more direct syntax). The upshot of all of this is that it's common to pass module names into places where you'd have one or more callbacks, where you might pass objects implementing some target interface in other languages.
The cowboy_rest behaviour then translates to one module (source file) per URL (pattern). Similarly, the Sumo DB persistence layer has one module per stored data object, and Sumo Rest tends to want the same modules for JSON-marshalable types.
The sample application then has a straightforward layout. There is a directory of models, one file per type, with storage and serialization information in each, and a separate directory of handlers, one file per URL pattern. While something needs to list out all of the route modules and data types, in general each handler module declares its own URL path.
(It's worth looking at the Cowboy REST list of callbacks and resulting HTTP status codes: this is a thing of beauty, compared to the, erm, wild west of Go's low-level net/http.)
The one other piece worth examining here is REST API documentation. I'd sort of been eyeing the Open API (Swagger) format, but assembling a massive JSON or YAML file for all of the endpoints felt like a hassle. An intermediate Erlang layer, Cowboy Trails, allows arbitrary metadata to be attached to each route in the handler module, and once you have that, Cowboy Swagger will generate the magic JSON file and browsable documentation for you. The key point here is that this is also defined in each individual handler source file.
The layout implications of this are useful and generic: one source file per type, where each type file defines its storage, serialization, and documentation; and one source file per route, where each route file has its own URL path, complete machine-processable documentation and metadata, and understands the standard failure cases. You just need the right high-level REST library in your language of choice to support this.
I found this finicky and prone to vague runtime errors. That's not important, though. The overall style of the system was pretty reasonable, and is probably a good way to write REST services in general.
Erlang's fundamental unit of code is a module, corresponding to a single source file. A module can implement a behaviour (always with British spelling), which is a set of required functions (in other words, an "interface" in Java- or Go-speak). You can pass an atom that is a module's name into apply/3 to dynamically call functions (and there might even be a more direct syntax). The upshot of all of this is that it's common to pass module names into places where you'd have one or more callbacks, where you might pass objects implementing some target interface in other languages.
The cowboy_rest behaviour then translates to one module (source file) per URL (pattern). Similarly, the Sumo DB persistence layer has one module per stored data object, and Sumo Rest tends to want the same modules for JSON-marshalable types.
The sample application then has a straightforward layout. There is a directory of models, one file per type, with storage and serialization information in each, and a separate directory of handlers, one file per URL pattern. While something needs to list out all of the route modules and data types, in general each handler module declares its own URL path.
(It's worth looking at the Cowboy REST list of callbacks and resulting HTTP status codes: this is a thing of beauty, compared to the, erm, wild west of Go's low-level net/http.)
The one other piece worth examining here is REST API documentation. I'd sort of been eyeing the Open API (Swagger) format, but assembling a massive JSON or YAML file for all of the endpoints felt like a hassle. An intermediate Erlang layer, Cowboy Trails, allows arbitrary metadata to be attached to each route in the handler module, and once you have that, Cowboy Swagger will generate the magic JSON file and browsable documentation for you. The key point here is that this is also defined in each individual handler source file.
The layout implications of this are useful and generic: one source file per type, where each type file defines its storage, serialization, and documentation; and one source file per route, where each route file has its own URL path, complete machine-processable documentation and metadata, and understands the standard failure cases. You just need the right high-level REST library in your language of choice to support this.
no subject