Mead.Session.History (mead v0.1.1)

Copy Markdown View Source

Keeps the turns of one conversation, and writes them through Mead.Session.Store when the session has a storage directory.

The state holds the turns with the newest first and the directory, or nil when persistence is off. Only append/2 is write-first: a turn that cannot be recorded is refused and memory is left untouched, so a conversation never accepts a turn it would forget. update_last/2 and mark_interrupted/1 always change memory and then try to write, because the caller already holds the answer; a closed turn that never reached the disk comes back after a restart as an interrupted one, which is accurate.

When the file passes :compact_after_bytes the history rewrites it from memory with Mead.Session.Store.compact/3; a failed rewrite is logged and never fails a write.

The agent is started before the session server, so a server crash leaves the history untouched.

Summary

Functions

Returns all turns in chronological order.

Records a turn as the newest one, or refuses it when it cannot be written.

Returns a specification to start this module under a supervisor.

Rewrites the file of the session as one record per turn, from the turns in memory.

Marks every turn still in progress as interrupted, and records that when there was one.

Starts the history for options[:session_id], registered under Mead.Registry.

Replaces the newest turn with the result of function applied to it.

Types

persistence_error()

@type persistence_error() :: {:error, {:persistence, term()}}

Functions

all(session_id)

@spec all(String.t()) :: [Mead.Session.Turn.t()]

Returns all turns in chronological order.

append(session_id, turn)

@spec append(String.t(), Mead.Session.Turn.t()) :: :ok | persistence_error()

Records a turn as the newest one, or refuses it when it cannot be written.

child_spec(arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

compact(session_id)

@spec compact(String.t()) ::
  {:ok, %{bytes_before: non_neg_integer(), bytes_after: non_neg_integer()}}
  | {:error, :not_found | :corrupt_history | {:persistence, term()}}

Rewrites the file of the session as one record per turn, from the turns in memory.

Returns the sizes before and after, {:error, :not_found} when there is no storage or no file yet, or the persistence error; the original file is untouched on an error.

mark_interrupted(session_id)

@spec mark_interrupted(String.t()) :: :ok | persistence_error()

Marks every turn still in progress as interrupted, and records that when there was one.

start_link(options)

@spec start_link(keyword()) :: Agent.on_start()

Starts the history for options[:session_id], registered under Mead.Registry.

:directory is where to write (or nil), :resume is a list of turns in chronological order to start from, and :compact_after_bytes is the file size from which the file is compacted (absent means never). :max_turns is how many of the newest turns a compaction keeps (absent means all).

update_last(session_id, function)

@spec update_last(String.t(), (Mead.Session.Turn.t() -> Mead.Session.Turn.t())) ::
  :ok | persistence_error()

Replaces the newest turn with the result of function applied to it.

Memory changes even when the write fails; the error tells the caller the disk is behind.