# `Electric.Replication.LogOffset`
[🔗](https://github.com/electric-sql/electric/tree/%40core/sync-service%401.5.1/packages/sync-service/lib/electric/replication/log_offset.ex#L1)

Uniquely identifies an operation inside the shape log.
Combines a transaction ID with operation ID.

# `int64`

```elixir
@type int64() :: 0..18_446_744_073_709_551_615
```

# `t`

```elixir
@type t() :: %Electric.Replication.LogOffset{
  op_offset: non_neg_integer() | :infinity,
  tx_offset: int64() | -1
}
```

# `t_tuple`

```elixir
@type t_tuple() :: {int64(), non_neg_integer() | :infinity}
```

# `before_all`

```elixir
@spec before_all() :: t()
```

An offset that is smaller than all offsets in the log.

## Examples

    iex> compare(before_all(), first())
    :lt

# `compare`

Compare two log offsets

## Examples

    iex> compare(new(10, 0), new(10, 1))
    :lt

    iex> compare(new(9, 1), new(10, 1))
    :lt

    iex> compare(new(10, 1), new(10, 0))
    :gt

    iex> compare(new(11, 1), new(10, 1))
    :gt

    iex> compare(new(0, 0), before_all())
    :gt

    iex> compare(new(10, 0), %LogOffset{tx_offset: 10, op_offset: 0})
    :eq

# `extract_lsn`

```elixir
@spec extract_lsn(t()) :: Electric.Postgres.Lsn.t()
```

Returns the LSN part of the LogOffset.

## Examples

    iex> extract_lsn(%LogOffset{tx_offset: 10, op_offset: 0})
    #Lsn<0/A>

    iex> extract_lsn(%LogOffset{tx_offset: 10, op_offset: 5})
    #Lsn<0/A>

    iex> extract_lsn(%LogOffset{tx_offset: 11, op_offset: 5})
    #Lsn<0/B>

    iex> extract_lsn(LogOffset.before_all())
    #Lsn<0/0>

# `first`

```elixir
@spec first() :: t()
```

The first possible offset in the log.

# `from_string`

```elixir
@spec from_string(String.t()) :: {:ok, t() | :now} | {:error, String.t()}
```

Parse the given string as a LogOffset value.

## Examples

    iex> from_string("-1")
    {:ok, before_all()}

    iex> from_string("now")
    {:ok, :now}

    iex> from_string("0_0")
    {:ok, %LogOffset{tx_offset: 0, op_offset: 0}}

    iex> from_string("11_13")
    {:ok, %LogOffset{tx_offset: 11, op_offset: 13}}

    iex> from_string("0_02")
    {:ok, %LogOffset{tx_offset: 0, op_offset: 2}}

    iex> from_string("0_inf")
    {:ok, %LogOffset{tx_offset: 0, op_offset: :infinity}}

    iex> from_string("1_2_3")
    {:error, "has invalid format"}

    iex> from_string("1_2 ")
    {:error, "has invalid format"}

    iex> from_string("10")
    {:error, "has invalid format"}

    iex> from_string("10_32.1")
    {:error, "has invalid format"}

# `increment`

Increments the offset of the change inside the transaction.

## Examples

    iex> increment(new(10, 5))
    %LogOffset{tx_offset: 10, op_offset: 6}

    iex> compare(new(10, 5) |> increment, new(10, 5))
    :gt

    iex> increment(new(10, 5), 5)
    %LogOffset{tx_offset: 10, op_offset: 10}

    iex> compare(new(10, 1) |> increment(4), new(10, 5))
    :eq

# `is_last_virtual_offset`
*macro* 

# `is_log_offset_lt`
*macro* 

Guard that checks if offset1 is less than offset2.

## Examples

    iex> LogOffset.is_log_offset_lt(new(10, 0), new(10, 1))
    true

    iex> LogOffset.is_log_offset_lt(new(9, 5), new(10, 1))
    true

    iex> LogOffset.is_log_offset_lt(new(10, 1), new(10, 0))
    false

    iex> LogOffset.is_log_offset_lt(new(10, 0), new(10, 0))
    false

    iex> LogOffset.is_log_offset_lt(new(10, 5), new(10, :infinity))
    true

    iex> LogOffset.is_log_offset_lt(new(10, :infinity), new(10, 5))
    false

    iex> LogOffset.is_log_offset_lt(new(10, :infinity), new(10, :infinity))
    false

    iex> LogOffset.is_log_offset_lt(new(9, :infinity), new(10, 0))
    true

# `is_log_offset_lte`
*macro* 

Guard that checks if offset1 is less than or equal to offset2.

## Examples

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, 0), new(10, 1))
    true

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, 0), new(10, 0))
    true

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, 1), new(10, 0))
    false

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, 5), new(10, :infinity))
    true

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, :infinity), new(10, :infinity))
    true

    iex> require LogOffset
    iex> LogOffset.is_log_offset_lte(new(10, :infinity), new(10, 5))
    false

# `is_min_offset`
*macro* 

# `is_real_offset`
*macro* 

# `is_virtual_offset`
*macro* 

# `last`

```elixir
@spec last() :: t()
```

The last possible offset in the log.

## Examples

    iex> compare(first(), last())
    :lt

    iex> compare(new(Lsn.from_integer(10), 0), last())
    :lt

# `last_before_real_offsets`

```elixir
@spec last_before_real_offsets() :: t()
```

The last possible offset for the "virtual" part of the log - i.e. snapshots.

# `max`

Get a maximum of 2 log offsets

## Examples

    iex> LogOffset.max(new(10, 0), new(10, 1))
    new(10, 1)

# `min`

Get a minimum of 2 log offsets

## Examples

    iex> LogOffset.min(new(10, 0), new(10, 1))
    new(10, 0)

# `new`

# `new`

Create a new LogOffset value.

## Examples

    iex> new(Lsn.from_integer(10), 0)
    %LogOffset{tx_offset: 10, op_offset: 0}

    iex> new(11, 3)
    %LogOffset{tx_offset: 11, op_offset: 3}

    iex> new(to_tuple(new(Lsn.from_integer(5), 1)))
    %LogOffset{tx_offset: 5, op_offset: 1}

    iex> new({11, 3})
    %LogOffset{tx_offset: 11, op_offset: 3}

    iex> new({11, 3.2})
    ** (FunctionClauseError) no function clause matching in Electric.Replication.LogOffset.new/2

    iex> new(10, -2)
    ** (FunctionClauseError) no function clause matching in Electric.Replication.LogOffset.new/2

# `to_int128`

Convert the log offset to a binary representation used on disk, sized to int128

# `to_iolist`

```elixir
@spec to_iolist(t()) :: iolist()
```

Format a LogOffset value to its text representation in an iolist.

## Examples
    iex> to_iolist(first())
    ["0", ?_, "0"]

    iex> to_iolist(new(Lsn.from_integer(10), 3))
    ["10", ?_, "3"]

    iex> to_iolist(before_all())
    ["-1"]

# `to_tuple`

```elixir
@spec to_tuple(t()) :: {int64(), non_neg_integer()}
```

Returns a tuple with the tx_offset and the op_offset.

## Examples
    iex> to_tuple(first())
    {0, 0}

    iex> to_tuple(new(Lsn.from_integer(10), 3))
    {10, 3}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
