Documentation ¶
Overview ¶
Package tableroll implements zero downtime upgrades between two independently managed processes.
An upgrade is coordinated over a well-known coordination directory. Any number of processes may be run at once that coordinate upgrades on that directory, and between those many processes, one is chosen to own all shareable / upgradeable file descriptors. Each upgrade uniquely involves two processes, and unix exclusive locks on the filesystem ensure that.
Each process under tableroll should be able to signal readiness, which will indicate to tableroll that it is safe for previous processes to cease listening for new connections and begin draining existing ones.
Unlike other upgrade mechanisms in this space, it is expected that a new binary is started independently, such as in a new container, not as a child of the existing one. How a new upgrade is started is entirely out of scope of this library. Both copies of the process must have access to the same coordination directory, but apart from that, there are no stringent requirements.
Index ¶
- Constants
- Variables
- type Conn
- type Fds
- func (f *Fds) Conn(id string) (net.Conn, error)
- func (f *Fds) DialWith(id, network, address string, ...) (net.Conn, error)
- func (f *Fds) File(id string) (*os.File, error)
- func (f *Fds) Listen(ctx context.Context, id string, cfg *net.ListenConfig, network, addr string) (net.Listener, error)
- func (f *Fds) ListenWith(id, network, addr string, ...) (net.Listener, error)
- func (f *Fds) Listener(id string) (net.Listener, error)
- func (f *Fds) OpenFileWith(id string, name string, openFunc func(name string) (*os.File, error)) (*os.File, error)
- func (f *Fds) Remove(id string) error
- func (f *Fds) String() string
- type Listener
- type Option
- type Upgrader
Constants ¶
const DefaultUpgradeTimeout time.Duration = time.Minute
DefaultUpgradeTimeout is the duration in which the upgrader expects the sibling to send a 'Ready' notification after passing over all its file descriptors; If the sibling does not send that it is ready in that duration, this Upgrader will close the sibling's connection and wait for additional connections.
Variables ¶
var ( // ErrUpgradeInProgress indicates that an upgrade is in progress. This state // is not necessarily terminal. // This error will be returned if an attempt is made to mutate the file // descriptor store while the upgrader is currently attempting to transfer // all file descriptors elsewhere. ErrUpgradeInProgress = errors.New("an upgrade is currently in progress") // ErrUpgradeCompleted indicates that an upgrade has already happened. This // state is terminal. // This error will be returned if an attempt is made to mutate the file // descriptor store after an upgrade has already completed. ErrUpgradeCompleted = errors.New("an upgrade has completed") // ErrUpgraderStopped indicates the upgrader's Stop method has been called. // This state is terminal. // This error will be returned if an atttempt is made to mutate the file // descriptor store after stopping the upgrader. ErrUpgraderStopped = errors.New("the upgrader has been marked as stopped") )
Functions ¶
This section is empty.
Types ¶
type Fds ¶
type Fds struct {
// contains filtered or unexported fields
}
Fds holds all shareable file descriptors, whether created in this process or inherited from a previous one. It provides methods for adding and removing file descriptors from the store.
func (*Fds) Conn ¶
Conn returns an inherited connection or nil.
It is the caller's responsibility to close the returned Conn at the appropriate time, typically when the Upgrader indicates draining and exiting is expected.
func (*Fds) DialWith ¶
func (f *Fds) DialWith(id, network, address string, dialFn func(network, address string) (net.Conn, error)) (net.Conn, error)
DialWith takess an id and a function that returns a connection (akin to net.Dial). If an inherited connection with that id exists, it will be returned. Otherwise, the provided function will be called and the resulting connection stored with that id and returned.
func (*Fds) Listen ¶
func (f *Fds) Listen(ctx context.Context, id string, cfg *net.ListenConfig, network, addr string) (net.Listener, error)
Listen returns a listener inherited from the parent process, or creates a new one. It is expected that the caller will close the returned listener once the Upgrader indicates draining is desired. The arguments are passed to net.Listen, and their meaning is described there.
func (*Fds) ListenWith ¶
func (f *Fds) ListenWith(id, network, addr string, listenerFunc func(network, addr string) (net.Listener, error)) (net.Listener, error)
ListenWith returns a listener with the given id inherited from the previous owner, or if it doesn't exist creates a new one using the provided function. The listener function should return quickly since it will block any upgrade requests from being serviced. Note that any unix sockets will have "SetUnlinkOnClose(false)" called on them. Callers may choose to switch them back to 'true' if appropriate. The listener function is compatible with net.Listen.
func (*Fds) Listener ¶
Listener returns an inherited listener with the given ID, or nil.
It is the caller's responsibility to close the returned listener once connections should be drained.
func (*Fds) OpenFileWith ¶
func (f *Fds) OpenFileWith(id string, name string, openFunc func(name string) (*os.File, error)) (*os.File, error)
OpenFileWith retrieves the given file from the store, and if it's not present opens and adds it. The required openFunc is compatible with `os.Open`.
type Option ¶
type Option func(u *Upgrader)
Option is an option function for Upgrader. See Rob Pike's post on the topic for more information on this pattern: https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
func WithLogger ¶
WithLogger configures the logger to use for tableroll operations. By default, nothing will be logged.
func WithUpgradeTimeout ¶
WithUpgradeTimeout allows configuring the update timeout. If a time of 0 is specified, the default will be used.
type Upgrader ¶
type Upgrader struct { Fds *Fds // contains filtered or unexported fields }
Upgrader handles zero downtime upgrades and passing files between processes.
func New ¶
New constructs a tableroll upgrader. The first argument is a directory. All processes in an upgrade chain must use the same coordination directory. The provided directory must exist and be writeable by the process using tableroll. Canonically, this directory is `/run/${program}/tableroll/`. Any number of options to configure tableroll may also be provided. If the passed in context is cancelled, any attempt to connect to an existing owner will be cancelled. To stop servicing upgrade requests and complete stop the upgrader, the `Stop` method should be called.
func (*Upgrader) Ready ¶
Ready signals that the current process is ready to accept connections. It must be called to finish the upgrade.
All fds which were inherited but not used are closed after the call to Ready.
func (*Upgrader) Stop ¶
func (u *Upgrader) Stop()
Stop prevents any more upgrades from happening, and closes the upgrade complete channel.
func (*Upgrader) UpgradeComplete ¶
func (u *Upgrader) UpgradeComplete() <-chan struct{}
UpgradeComplete returns a channel which is closed when the managed file descriptors have been passed to the next process, and the next process has indicated it is ready.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
internal
|
|
proto
Package proto encapsulates the types used to communicate between multiple tableroll processes at various versions, as well as the functions for reading and writing this data off the wire.
|
Package proto encapsulates the types used to communicate between multiple tableroll processes at various versions, as well as the functions for reading and writing this data off the wire. |