\Drupal\strata\Codec PipeCodec

Shared machinery for a codec that shells out to a compressor on disk.

A PHP extension is a build-time decision and a binary is a package-manager one, so the two are absent on different hosts. zstd and brotli are both on the PATH of a great many machines whose PHP was built without the matching extension, and reading a frame back matters more than writing one quickly: a bucket written on a box with ext-brotli has to stay readable on a box without it, or the backup is not a backup.

Nothing built on this may be a per-frame writer. A process spawn dominates the work at frame sizes - 1,000 separate zstd invocations measured 5.88 seconds against sub-millisecond compression - so CodecRegistry::register() takes these with $perFrame FALSE, and they serve reading, compaction, dictionary training and export instead. PipeCodec::compress() spawns once per call and is correct for a one-off; PipeCodec::compressBatch() runs the binary ONCE across the whole batch, which is what bulk work uses.

Both binaries follow the same file convention, which is what lets one implementation drive them: given several inputs they write beside each one, adding the suffix when compressing and stripping it when decompressing. A batch is therefore laid out as <n> and <n><suffix> in a private scratch directory and read back by name.

Summary

Methods
Properties
Constants
__construct
isAvailable
unavailableReason
supportsDictionary
compress
decompress
compressBatch
decompressBatch
No public properties found
No public constants found
binaryName
suffix
arguments
No protected properties found
No protected constants found
batch
run
clamp
resolveBinary
canSpawn
makeScratchDirectory
removeDirectory
assertAvailable
binary
resolved
spawns
binaryPath
scratchDirectory
TIMEOUT
COMMON_DIRECTORIES

Constant

TIMEOUT

TIMEOUT = 300

Seconds a single binary invocation may run before it is killed.

COMMON_DIRECTORIES

COMMON_DIRECTORIES = ['/usr/bin', '/usr/local/bin', '/bin', '/opt/homebrew/bin', '/opt/local/bin', '/snap/bin']

Directories searched after PATH.

A php-fpm pool frequently runs with a minimal PATH that a login shell does not have, so a binary the operator can see is regularly one PHP cannot. These are where the common package managers put one.

Properties

$binary

$binary : ?string

Resolved absolute path to the binary, or NULL when it has not been looked up yet.

Type

string|null

$resolved

$resolved : bool

Whether the lookup has run, so a negative result is not retried on every call.

Type

bool

$spawns

$spawns : int

How many processes this instance has spawned.

Type

int

$binaryPath

$binaryPath : ?string

Type

string|null

$scratchDirectory

$scratchDirectory : ?string

Type

string|null

Methods

__construct()

__construct(string|null  $binaryPath = null, string|null  $scratchDirectory = null) : mixed

Constructs the codec.

Parameters

string|null $binaryPath

An explicit path to the binary, or NULL to search PATH and the common directories.

string|null $scratchDirectory

Directory for batch scratch files, or NULL for the system temporary directory.

Returns

mixed —

isAvailable()

isAvailable() : bool

Whether this codec can run on this host right now.

Returns

bool —

TRUE when every extension or binary the codec needs is present.

unavailableReason()

unavailableReason() : string|null

Why the codec is unavailable, for the settings form and hook_requirements().

Returns

string|null —

A short human-readable reason, or NULL when the codec is available.

supportsDictionary()

supportsDictionary() : bool

Whether the codec accepts a training dictionary.

Returns

bool —

TRUE when compress() and decompress() honour their $dictionary argument.

compress()

compress(string  $data, ?int  $level = null, ?string  $dictionary = null) : string

Compresses a buffer.

Parameters

string $data

The bytes to compress. An empty string compresses to an empty string, so that an absent payload never becomes a non-empty frame.

?int $level

A level within CompressionCodecInterface::levels(), or NULL for the default.

?string $dictionary

Raw dictionary bytes, or NULL. Ignored by codecs that report no dictionary support, so a caller never has to branch on it.

Returns

string —

The compressed bytes.

decompress()

decompress(string  $data, ?string  $dictionary = null) : string

Decompresses a buffer.

Parameters

string $data

The compressed bytes.

?string $dictionary

The same dictionary bytes used to compress, or NULL.

Returns

string —

The original bytes.

compressBatch()

compressBatch(list  $buffers, int|null  $level = null, string|null  $dictionary = null) : list<string>

Compresses many buffers in one process.

Parameters

list $buffers

The buffers to compress, in order.

int|null $level

A level within PipeCodec::levels(), or NULL for the default.

string|null $dictionary

Raw dictionary bytes, or NULL.

Throws

\RuntimeException

When the codec is unavailable, or the binary fails.

Returns

list

The compressed buffers, in the same order.

decompressBatch()

decompressBatch(list  $buffers, string|null  $dictionary = null) : list<string>

Decompresses many buffers in one process.

Parameters

list $buffers

The buffers to decompress, in order.

string|null $dictionary

The same dictionary bytes used to compress, or NULL.

Throws

\RuntimeException

When the codec is unavailable, or the binary fails.

Returns

list

The original buffers, in the same order.

binaryName()

binaryName() : string

The executable this codec drives, as it is named on the PATH.

Returns

string —

The file name, with no directory.

suffix()

suffix() : string

The extension the binary appends to a compressed file.

Returns

string —

The suffix, leading dot included.

arguments()

arguments(bool  $compressing, int  $level, string|null  $dictionaryPath) : list<string>

The flags one invocation runs with, before the input paths.

Parameters

bool $compressing

TRUE to compress, FALSE to decompress.

int $level

A level already brought into range by PipeCodec::clamp().

string|null $dictionaryPath

Where the dictionary was written, or NULL when there is none.

Returns

list

The arguments, without the binary itself.

batch()

batch(list  $buffers, bool  $compressing, int|null  $level, string|null  $dictionary) : list<string>

Runs one binary invocation across a whole batch.

Parameters

list $buffers

The buffers to process, in order.

bool $compressing

TRUE to compress, FALSE to decompress.

int|null $level

Compression level, ignored when decompressing.

string|null $dictionary

Raw dictionary bytes, or NULL.

Throws

\RuntimeException

When the codec is unavailable, or the binary fails.

Returns

list

The processed buffers, in the same order.

run()

run(list  $command) : void

Executes one command and fails loudly on a non-zero exit.

Parameters

list $command

The argument vector. Never a shell string, so a path with a space or a quote cannot become an injection.

Throws

\RuntimeException

When the process cannot start, times out, or exits non-zero.

Returns

void —

clamp()

clamp(int|null  $level) : int

Brings a requested level into the supported range.

Parameters

int|null $level

The requested level, or NULL for the default.

Returns

int —

A level this codec accepts.

resolveBinary()

resolveBinary() : string|null

Locates the binary once and caches the answer, including a negative one.

Returns

string|null —

An absolute path, or NULL when the binary is not present.

canSpawn()

canSpawn() : bool

Whether this PHP is allowed to start a process at all.

Returns

bool —

TRUE when proc_open() is neither missing nor in disable_functions.

makeScratchDirectory()

makeScratchDirectory() : string

Creates a private scratch directory for one batch.

Throws

\RuntimeException

When the directory cannot be created.

Returns

string —

An absolute path with no trailing slash.

removeDirectory()

removeDirectory(string  $path) : void

Removes a scratch directory and everything under it.

Parameters

string $path

The directory to remove.

Returns

void —

assertAvailable()

assertAvailable() : void

Guards every entry point.

Throws

\RuntimeException

When the binary cannot be run.

Returns

void —