Sailhouse is currently not available for public access, but will be soon! 🎉
Sailhouse is a platform all about the developer experience. It’s optimised to move quickly, with confidence, allowing engineers to focus on the product, not the tooling.
Sailhouse is split into verticals called “apps”. These are flexible enough to be anything you would want to use.
- Environments (
production
,staging
or even isolated dev environments) - Individual applications
- … I’ve run out of ideas
Everything happens within the context of an application, subscriptions live on topics, topics live on apps etc.
> sailhouse apps list
sailhouse-staging
sailhouse-production
sailhouse-demo
And you can create a new one really easily
sailhouse apps create lets-go
Schemaless development
Schemas are a core, and powerful, tool available to developers on Sailhouse. However, flexibility is paramount, even on an opinionated platform.
Using the CLI
Both topics and subscriptions can be created easily from the command line.
Let’s create a topic called project-added
.
sailhouse topics create project-added
In our demo scenario, every day we want to fetch the latest projects added and send a slack digest, so let’s create a slack-notification
subscription.
sailhouse subs create project-added slack-notification
By default, the CLI runs against the currently selected app and team, but this can be easily overriden with the
--app
and--team
global flags.
And there you have it, a topic and subscription set-up and ready to go!
Self Healing
Sailhouse offers self-healing on topics and subscriptions, making it possible to develop an application without even touching the CLI.
When an event is sent to a topic that doesn’t exist, such as project-added
, Sailhouse will automatically create the topic and store the event.
Likewise, when you attempt to pull events from a subscription that doesn’t exist, Sailhouse will create the subscription and back-fill events sent within the default_window
property you define in the getEvents(...)
call.
Although not advised for production, this is great for rapid development which can then be backported to a schema for more a more maintainable infrastructure.
But I want a schema?
Then you’re in the right place!
Sailhouse schemas can be “sharded”. This means, you can split definitions over several files, repos, git providers, even source control software! I’m kidding on the last bit, don’t do that.
Each Schema has a key
, a short string used to say “Hey, all resources with this key belong to me”. This is how you can create, delete, update resources with relatively complex dependencies. The ownership is split, and the platform doesn’t let you delete if there are dependencies.
key="main"
[[topics]]
slug="project-added"
[[subscriptions]]
slug="slack-notification"
topic="project-added"
type="pull"
[[subscriptions]]
slug="update-billing"
topic="project-added"
type="push"
endpoint="https://project.app/hooks/add-project-billing"
You may have expected subscriptions to live under topics. But as we mentioned earlier, schemas are sharded, and therefor considered partial. To give the most flexibility, both topics
and subscriptions
are top-level arrays on a schema file.
Working on Netlify
Sailhouse was built with serverless in mind. It’s not a case of it only working with severless, but it’s an area that benefits a huge amount from the DX improvements offered by Sailhouse.
import { SailhouseClient } from "@sailhouse/client";
const client = new SailhouseClient();
export const handler = async (event, context) => {
const { repo, name } = JSON.parse(event.body);
await client.sendEvent("project-added", { repo, name });
return {
statusCode: 200,
};
};
Let’s say, every day we want to pull all the new projects created and send a slack message notifying us of how many.
import { SailhouseClient } from '@sailhouse/client';
import { schedule } from '@netlify/functions';
import { sendSlackMessage } from '../utils';
const client = new SailhouseClient();
interface ProjectAddedEvent {
repo: string;
name: string;
}
const dailySlackSummary = async () => {
// Fetch all unacknowledged events on the
// "slack-notification" subscription
const events = await client.getEvents<ProjectAddedEvent>(
'project-added',
'slack-notification'
);
const count = events.length;
const names = events.map(e => e.data.name);
await sendSlackMessage(
`We have ${count} new projects! ${names.join(" 🎉\n")}`
);
// Acknowledge all the events we've just processed
await Promise.all(events.map(e => e.ack()));
return {
statusCode: 200;
}
};
export const handler = schedule("@daily", dailySlackSummary);
Making use of Netlify’s Scheduled Functions it’s trivial.
Fin
And that’s Sailhouse 101! Truly, that simple.
If you want to get in early, reach out over email or reach me on twitter.