Event ingestion client
A small API client with optional fields and a record of functions as an object.
module highstorm
import (
nanyx.web/http
nanyx.web/json
)
-- A small client for an event-ingestion API, showing optional fields,
-- a record of functions as an "object", and `proc` for error chaining.
type Event = (
event: string
time?: int
content?: string
metadata?: map(string, string)
)
type Options = (
token: string
baseUrl?: string
)
type IngestError = #httpError(int) | #badResponse
type Client = (
baseUrl: string
ingest: [Http] (channel: string, event: Event) -> #some(id: string) | #error(IngestError)
)
def checkOk: Response -> #some(Response) | #error(#httpError(int)) = { response ->
if response.ok then #some(response) else #error(#httpError(response.status))
}
def idDecoder = Json.record(id = Json.field("id", Json.string))
export def Client.new: Options -> Client = { options ->
def #some(baseUrl) = options.baseUrl except #none -> #some("https://highstorm.app")
Client(
baseUrl = baseUrl
ingest = { channel, event -> proc {
def response = try Http.post(
url = "{baseUrl}/api/v1/events/{channel}"
headers = [
"Content-Type" => "application/json"
"Authorization" => "Bearer {options.token}"
]
body = Json.encode(event)
) \Result.then(checkOk)
def body = try Json.decode(response.body, idDecoder) \Result.mapError { _ -> #badResponse }
return body
}}
)
}
@entry
def main: [Console & Http] () -> () = {
def client = Client.new(Options(token = "secret"))
match client.ingest(channel = "deploys", event = Event(event = "deploy.finished", content = "v1.2.0"))
| #some(id = id) -> println("Ingested event {id}")
| #error(#httpError(status)) -> println("HTTP error {status}")
| #error(#badResponse) -> println("Could not read the response")
}
This program lives in the repository as examples/EventSubscription.nyx.