apirev

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package apirev is the API revision as a value.

The generated server reads a revision off every request and the generated client sends one, both as a string. This is what that string becomes once somebody wants to compare it: the date an API surface was cut, and the one question worth asking about it — was the caller built before some point.

Nothing here is per project, which is why it is in the runtime rather than generated into every `api` package. A compatibility shim written against it reads the same in every service in every project.

The type exists mostly so that a date written down in source cannot be wrong in a way nobody notices. MustParse is what a shim declares its cutoff with, and it panics: a mistyped date in a `var` initializer stops the process before it serves anything, rather than becoming a branch that silently never runs.

Index

Examples

Constants

View Source
const Layout = "2006-01-02"

Layout is how a revision is written.

A date and nothing finer: the question a revision answers is "how many releases behind is this client", and an hour has never been the unit of that answer.

Variables

This section is empty.

Functions

This section is empty.

Types

type Revision

type Revision struct {
	// contains filtered or unexported fields
}

Revision is a point on an API's own timeline.

The zero value is unknown, and unknown is an ordinary thing for a caller to be: a curl sends no revision, a hand-rolled client sends no revision, and anything sending nonsense has said nothing useful. Every comparison here reads unknown as current — see Revision.Before — so a caller rig cannot place on the timeline gets today's behavior rather than a compatibility path nobody can show it needs.

func MustParse

func MustParse(date string) Revision

MustParse is for a revision written down in source: a compatibility shim's cutoff, or a Revision a server refuses below.

var notesAdded = apirev.MustParse("2026-04-30")

It panics on anything that is not a date. That is the point of it existing beside Parse: a cutoff is a constant, a typo in one is a bug rather than bad input, and a shim that quietly never fires is the worst way to find out. Declared at package scope, the panic lands at startup.

func Parse

func Parse(date string) (Revision, bool)

Parse is for a revision that arrived from somewhere — a request header, a configuration file — where being wrong is ordinary rather than a bug.

ok is false for a string that is not a date, and equally for the empty string. They are the same answer on purpose: both mean this caller cannot be placed on the timeline, and splitting them would invite a caller to be treated as old for saying nothing.

Example

An unknown revision reads as current, which is the safety property: a curl or a hand-rolled client sends nothing, and nothing should not select a compatibility path that only an old generated client needs.

package main

import (
	"fmt"

	"github.com/simonjanss/rig/runtime/apirev"
)

func main() {
	rev, ok := apirev.Parse("not a date")

	fmt.Println(ok, rev.Known())
	fmt.Printf("%q\n", rev.String())

}
Output:
false false
""

func (Revision) Before

func (r Revision) Before(other Revision) bool

Before reports whether r was cut before other.

False when either side is unknown, which is the whole safety property: a shim guarded by `rev.Before(cutoff)` does not fire for a caller that said nothing, and a server whose minimum is unset refuses nobody. Neither case needs the caller to remember a check.

Example

A service reads the revision a caller was built against off the request and decides what to send it. Callers older than the cutoff get the old shape.

package main

import (
	"fmt"

	"github.com/simonjanss/rig/runtime/apirev"
)

// notesAdded is how a compatibility shim declares its cutoff: a package-level
// var, so a mistyped date panics at startup rather than becoming a branch that
// silently never runs.
var notesAdded = apirev.MustParse("2026-04-30")

func main() {
	for _, header := range []string{"2026-01-15", "2026-08-01", ""} {
		rev, ok := apirev.Parse(header)

		fmt.Printf("%-12q parsed=%-5t old=%t\n", header, ok, rev.Before(notesAdded))
	}

}
Output:
"2026-01-15" parsed=true  old=true
"2026-08-01" parsed=true  old=false
""           parsed=false old=false

func (Revision) Known

func (r Revision) Known() bool

Known reports whether this is a revision at all.

It is the honest form of the question Revision.Before answers safely: an unknown revision compares as current, so code that needs to count the callers it cannot place has to ask directly.

func (Revision) String

func (r Revision) String() string

String is the revision as it travels, and empty for an unknown one — so a log line that prints it says nothing rather than saying the wrong year.

Rendered when the revision was parsed rather than here. It is on the way out of every response a generated server writes, and a date formatted per request is an allocation per request for an answer that cannot change.

func (Revision) Sub

func (r Revision) Sub(other Revision) time.Duration

Sub is how much older r is than other, or a negative duration the other way around. Zero when either side is unknown.

The unit is whole days, because Layout is.

Example

Sub is in whole days, because a revision is a date — "how many releases behind is this caller" has never been an hourly question.

package main

import (
	"fmt"

	"github.com/simonjanss/rig/runtime/apirev"
)

func main() {
	old := apirev.MustParse("2026-04-30")
	recent := apirev.MustParse("2026-05-10")

	fmt.Println(recent.Sub(old))
	fmt.Println(old.Sub(recent))

}
Output:
240h0m0s
-240h0m0s

func (Revision) Time

func (r Revision) Time() time.Time

Time is the revision as an instant, at midnight UTC. The zero time.Time for an unknown revision.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL