compensate

package
v0.69.0 Latest Latest
Warning

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

Go to latest
Published: Aug 7, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package compensate provides a disk-spooled compensation log for cloud blob transactions.

A cloud bucket has no transaction primitive, so a commit that fails partway through must undo the object mutations it already applied. Undoing an overwrite needs the object's prior bytes, but holding every prior value in memory would let one multi-key commit (a block plus its metadata and indexes) retain gigabytes. This log spools prior values to a temporary file and keeps only their offsets in memory, and records nothing at all for keys that did not previously exist — the common append-only case, whose undo is a delete.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Log

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

Log records the pre-commit state of every object a commit is about to change. A Log is not safe for concurrent use; a blob transaction commits from a single goroutine.

func NewLog

func NewLog(namePattern string) (*Log, error)

NewLog creates an empty compensation log. The caller must Close it to release the spool file, whether or not the commit succeeds.

func (*Log) Close

func (l *Log) Close() error

Close releases and removes the spool file. It is safe to call more than once.

func (*Log) Len

func (l *Log) Len() int

Len returns the number of recorded entries. Entry i corresponds to the i'th key the commit applies, so Undo(i) reverses exactly the changes already made when the i'th key failed.

func (*Log) RecordMissing

func (l *Log) RecordMissing(key string)

RecordMissing notes that key had no object before the commit, so undoing a write to it means deleting it. No spool space is used.

func (*Log) RecordValue

func (l *Log) RecordValue(key string, value []byte) error

RecordValue spools key's prior bytes so an overwrite or delete can be undone.

func (*Log) RecordValueFrom

func (l *Log) RecordValueFrom(key string, r io.Reader) error

RecordValueFrom streams key's prior bytes from r into the spool instead of buffering them first. Callers pass the raw object reader, deliberately not a size-capped one: the cap on ordinary reads exists to bound memory, and this path never holds the value in memory, so applying it here would make an object larger than the cap impossible to overwrite or delete inside a transaction. Spool space is bounded by the size of the objects a single commit replaces.

func (*Log) Undo

func (l *Log) Undo(
	n int,
	put func(key string, value *io.SectionReader, size int64) error,
	del func(key string) error,
) error

Undo reverses the first n recorded changes, most recent first. Restoring an object that existed calls put with a reader over its spooled prior bytes and their length; one that did not exist calls del. put receives a reader rather than a []byte so a large prior value is streamed back out of the spool instead of being materialized — otherwise spooling the capture side would still leave the restore side able to exhaust memory. The reader is an *io.SectionReader, so it also satisfies io.ReadSeeker for SDKs that need to rewind.

Every entry is attempted even after a failure, so a single unreachable key does not abandon the rest of the compensation. The returned error joins all failures; a non-nil result means the bucket is left partially committed and callers must surface that rather than reporting a clean rollback.

Jump to

Keyboard shortcuts

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