Categorygithub.com/rotationalio/go-ensign
modulepackage
0.12.0
Repository: https://github.com/rotationalio/go-ensign.git
Documentation: pkg.go.dev

# README

Ensign Go SDK

Go Reference Go Report Card CI

Welcome to go-ensign!

This repository contains the Ensign driver, SDK, and helpers for Go. For the main ensign repo, go here. We also have SDKs for Javascript and Python.

The getting started guide and general documentation can be found at https://ensign.rotational.dev. You may also want to reference the GoDoc Package Documentation as well.

Creating an Ensign Client

To add the Go SDK as a dependency, either go get it or import it and run go mod tidy:

$ go get github.com/rotationalio/go-ensign

The Go SDK provides a client that is able to connect to an Ensign system in order to manage topics, publish events, and subscribe to an event stream. At a minimum, you need API credentials, which can be obtained by creating an account at https://rotational.app. Once you've created an account and downloaded your credentials, you can instantiate a new Ensign client and check to make sure you're connected:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/rotationalio/go-ensign"
)

func main() {
	client, err := ensign.New(ensign.WithCredentials("CLIENT ID", "CLIENT SECRET"))
	if err != nil {
		log.Fatal(err)
	}

	status, err := client.Status(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%+v\n", status)
}

You can also set the $ENSIGN_CLIENT_ID and $ENSIGN_CLIENT_SECRET environment variables so that you can instantiate the Client without specifying credentials in code.

// Assumes that $ENSIGN_CLIENT_ID and $ENSIGN_CLIENT_SECRET are set
client, err := ensign.New()

Finally, if you downloaded the client.json file from the app; you can load it by specifying the path to the JSON file:

client, err := ensign.New(ensign.WithLoadCredentials("path/to/client.json"))

Topic Management

Every topic that you work with is like a database table or collection of tables -- it is where your event data lives. Naturally, this is generally a starting place to interacting with Ensign. While you can create and manage topics from Beacon -- our Ensign UI -- you can also create and manage topics with the SDK.

Generally speaking, at the beginning of each Ensign program, you'll want to check if a topic exists and create it if it doesn't. This can be done with the following code:

const TopicName = "my-awesome-topic"

var client *ensign.Client

func checkTopic() (err error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	var exists bool
	if exists, err = client.TopicExists(ctx, TopicName); err != nil {
		return err
	}

	if !exists {
		var topicID string
		if topicID, err = client.CreateTopic(ctx, TopicName); err != nil {
			return err
		}
		log.Printf("created topic %s with ID %s\n", TopicName, topicID)
	}
	return nil
}

You can also list all the topics in your current project as follows:

func printAllTopics() error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	topics, err := client.ListTopics(ctx)
	if err != nil {
		return err
	}

	for _, topic := range topics {
		fmt.Printf("%s: %s\n", topic.Id, topic.Name)
	}
	return nil
}

Topic Cache

If you're going to be working with a lot of topics, you can use the topics.Cache to simplify topic management. Create the cache as follows:


import (
	"github.com/rotationalio/ensign"
	ensignTopics "github.com/rotationalio/ensign/topics"
)

var (
	client *ensign.Client
	topics *ensignTopics.Cache
)

func connect() (err error) {
	if client, err = ensign.New(); err != nil {
		return err
	}

	topics = ensignTopics.NewCache(client)
	return nil
}

With the topics cache in place you can simplify the "check if topic exists and create if it doesn't" code by using the Ensure() method:

const TopicName = "my-awesome-topic"

func checkTopic() (err error) {
	if _, err = topics.Ensure(TopicName); err != nil {
		return err
	}
	return nil
}

The cache also prevents repeated calls to Ensign, so you can use the Exists and Get method instead of client.TopicExists and client.TopicID.

Events

The Event data structure is how you can create data to send to Ensign and your downstream subscribers, and how you will receive data from Ensign. At it's core, an event is an application-defined datagram that you can use to create totally ordered data flows.

There are two pieces user-specified information that are part of the event, the Metadata: user-defined key/value pairs of strings that can be used for querying and indexing events, and the Data, generic data that you can use that define the event.

To parse and work with events, there are two pieces of information: the Mimetype, e.g. application/json, which helps you determine how to parse the Data and the Type, a user defined schema that can be used to validate or verify the event once parsed. For more on types and mimetypes, see the Ensign documentation.

Publishing Events

To publish an event to a topic, you create an event, and then use the clients, Publish method as follows:

var client *ensign.Client

func publishMessages() {
	for i := 0; i < 100; i++ {
		// Create a simple event
		msg := &ensign.Event{Data: []byte(fmt.Sprintf("event no. %d", i+1))}}

		// Publish the event
		if err := client.Publish("example-topic", msg); err != nil {
			panic(err)
		}

		// Determine if the event was published or not
		if _, err := msg.Nacked(); err != nil {
			panic(err)
		}

		time.Sleep(time.Second)
	}
}

When publishing events you can check if the event was acked (sucessfully published) or nacked (there was an error during publishing) using the Acked() and Nacked() methods of the Event that you created.

Subscribing

To subscribe to events on a topic or topics, you can create an object with a channel to receive events on.

var client *ensign.Client

func subscribeEvents() {
	sub, err := client.Subscribe("example-topic-a", "example-topic-b")
	if err != nil {
		panic(err)
	}

	for event := range sub.C {
		if err := handleEvent(event); err != nil {
			event.Nack(api.Nack_UNPROCESSED)
		} else {
			event.Ack()
		}
	}
}

func handleEvent(event *ensign.Event) error {
	// handle each event as it comes in.
}

It is important to let Ensign know if the event was processed successfully using the Ack and Nack methods on the event -- this will help Ensign determine if it needs to resend the event or not.

Quick API Reference

  • New: create a new Ensign client with credentials from the environment or from a file.
  • Event: the event data structure for publishing and subscribing.
  • client.Publish: publish one or more events to a specified topic.
  • client.Subscribe: create a Subscription with a channel to receive incoming events on.
  • Subscription: the object return from a Subscribe operation, with an events channel, C to listen for events on.
  • client.TopicExists: check if a topic with the specified name exists in the project.
  • client.CreateTopic: create a topic with the specified name in the project.
  • client.ListTopics: list all the topics in the project.
  • client.TopicID: get the topic ID from a topic name.
  • cache.Get: get a topic ID from a topic name.
  • cache.Exists: check if the specified topic exists.
  • cache.Ensure: a helper for "create topic if it doesn't exist".
  • cache.Clear: empty the internal cache to fetch data from ensign again.
  • cache.Length: returns the number of items in the topic cache.

# Packages

No description provided by the author
Package auth enables an Ensign client to authenticate with Ensign's Authn and Authz service called Quarterdeck.
No description provided by the author
Package mock implements an in-memory gRPC mock Ensign server that can be connected to using a bufconn.
No description provided by the author
Package stream provides */.
No description provided by the author

# Functions

Create a new Ensign client, specifying connection and authentication options if necessary.
Creates a new incoming event as though it were from a subscription.
NewOptions instantiates an options object for configuring Ensign, sets defaults and loads missing options from the environment, then validates the options; returning an error if the options are incorrectly configured.
Creates a new outgoing event to be published.
NewQueryCursor creates a new query cursor that reads from the specified stream.
Version returns the semantic version for the current build.
WithAuthenticator specifies a different Quarterdeck URL or you can supply an empty string and noauth set to true to have no authentication occur with the Ensign client.
WithCredentials allows you to instantiate an Ensign client with API Key information.
WithEnsignEndpoint allows you to specify an endpoint that is not the production Ensign cloud.
WithLoadCredentials loads the Ensign API Key information from the JSON file that was download from the Rotational web application.
WithMock connects ensign to the specified mock ensign server for local testing.
WithOptions sets the options to the passed in options value.

# Constants

Default connection endpoints to the production Ensign cluster.
The default page size for paginated gRPC responses.
Default connection endpoints to the production Ensign cluster.
Environment variables for configuring Ensign.
APIKeys you receive when creating a project on https://rotational.app will return a Client ID and Client Secret.
Environment variables for configuring Ensign.
The following environment variables allow you to connect to another Ensign service.
Environment variables for configuring Ensign.
Environment variables for configuring Ensign.
Specifies the wait period before checking if a gRPC connection has been established while waiting for a ready connection.
The Go SDK user agent format string.
Version component constants for the current build.
Version component constants for the current build.
Version component constants for the current build.
Version component constants for the current build.
Version component constants for the current build.

# Variables

Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.
Standardized errors that the client may return from configuration issues or parsed from gRPC service calls.

# Structs

Client manages the credentials and connection to the Ensign server.
Events wrap user-defined datagrams that are totally ordered by the Ensign platform.
A Nack from the server on a publish stream indicates that the event was not successfully published for the reason specified by the code and the message.
Options specifies the client configuration for authenticating and connecting to the Ensign service.
QueryCursor exposes event results from an EnSQL query with familiar database cursor semantics.
A Subscription object with a channel of events is returned when you subscribe to a topic or topics.

# Interfaces

Acknowledger allows consumers to send acks/nacks back to the server when they have successfully processed an event.

# Type aliases

Metadata are user-defined key/value pairs that can be optionally added to an event to store/lookup data without unmarshaling the entire payload.
Option allows users to specify variadic options to create & connect the Ensign client.