DiscordPHP-BridgeBot Documentation

JsonFile
in package

FinalYes

A JSON document on disk that survives restarts, crashes and a careless text editor — and that is written without stopping the event loop.

Store is this file with the bridges in it — which Discord channel every connector is relaying with, across every server the bot is in. Losing that silently is the worst thing the bot can do: a bridge that disappears looks exactly like one that was never configured, and the person who set it up is not watching the log.

It is deliberately generic rather than part of Store, because a connector that needs its own state on disk should get these guarantees by using this class, not by writing a third copy of them.

Surviving

  • Writes are atomic. Content goes to a temp file and is renamed over the target, so a crash mid-write cannot leave a half-written document where the state used to be.
  • The last good copy is kept beside it as .bak, written after each successful save — not by copying the file about to be replaced, which would leave the backup one write behind.
  • A damaged file is never silently replaced. If the JSON does not parse, the backup is tried; if that fails too, the file is preserved under a .corrupt-<timestamp> name and the caller starts empty. Without that, one truncated file plus one link command is every server's bridges gone with nothing left to recover from.
  • Anything noticed on the way in is recorded in warnings(), which the bot logs at startup and reports to its owner.

Not blocking the loop

Loading is synchronous, once, during construction: it happens before run(), when there is no loop to block. Saving is not — a link lands while the bot is relaying everything else — so it goes through Filesystem, and the caller never waits: save() records the new state and returns, writes that arrive during one already in flight collapse into a single follow-up, and only the newest state is written.

Table of Contents

Constants

BACKUP_SUFFIX  : mixed = '.bak'
Where the last known-good copy is kept.

Properties

$dirty  : bool
Whether {@see save()} was called while that write was in flight.
$filesystem  : Filesystem
$path  : string
$pending  : array<string|int, mixed>
The newest state handed to {@see save()}.
$warnings  : array<int, string>
$writing  : PromiseInterface|null
The write in flight, if any.

Methods

__construct()  : mixed
filesystem()  : Filesystem
The backend in use, for the startup line.
flush()  : bool
Writes the newest state now, blocking.
load()  : array<string|int, mixed>
Reads the document, falling back to the backup and refusing to discard one it cannot understand.
path()  : string
save()  : void
Records new state and schedules a write. Returns immediately.
saved()  : PromiseInterface
Resolves when everything saved so far has reached the disk, following the queue to the end.
warnings()  : array<int, string>
Anything that went wrong while reading, in the order it was found. Empty on a normal start.
decode()  : array<string|int, mixed>|null
Reads and decodes one file, or `null` when it is missing, unreadable, or not a JSON object.
encode()  : string|null
write()  : PromiseInterface
Encode, write a temp file, rename it over the target, then write the backup.

Constants

BACKUP_SUFFIX

Where the last known-good copy is kept.

public mixed BACKUP_SUFFIX = '.bak'

Properties

$dirty

Whether {@see save()} was called while that write was in flight.

private bool $dirty = false

$pending

The newest state handed to {@see save()}.

private array<string|int, mixed> $pending = []

$warnings

private array<int, string> $warnings = []

$writing

The write in flight, if any.

private PromiseInterface|null $writing = null

Methods

__construct()

public __construct(string $path[, Filesystem|null $filesystem = null ]) : mixed
Parameters
$path : string
$filesystem : Filesystem|null = null

flush()

Writes the newest state now, blocking.

public flush() : bool

For shutdown: the loop is about to stop, so a queued write would never run. Everything else should use save().

Return values
bool

load()

Reads the document, falling back to the backup and refusing to discard one it cannot understand.

public load() : array<string|int, mixed>
Return values
array<string|int, mixed>

path()

public path() : string
Return values
string

save()

Records new state and schedules a write. Returns immediately.

public save(array<string|int, mixed> $data) : void
Parameters
$data : array<string|int, mixed>

saved()

Resolves when everything saved so far has reached the disk, following the queue to the end.

public saved() : PromiseInterface
Return values
PromiseInterface

warnings()

Anything that went wrong while reading, in the order it was found. Empty on a normal start.

public warnings() : array<int, string>
Return values
array<int, string>

decode()

Reads and decodes one file, or `null` when it is missing, unreadable, or not a JSON object.

private static decode(string $path) : array<string|int, mixed>|null
Parameters
$path : string
Return values
array<string|int, mixed>|null

encode()

private static encode(array<string|int, mixed> $data) : string|null
Parameters
$data : array<string|int, mixed>
Return values
string|null

write()

Encode, write a temp file, rename it over the target, then write the backup.

private write() : PromiseInterface

Bails without touching the live file when the data cannot be encoded — a module stashing a non-UTF-8 string, say — so a bad value never truncates the state.

Return values
PromiseInterface
On this page

Search results