Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## v0.7.4 (2026-04-13)

### Bug fixes

* (#93) Fixed the Mapper used by GetMappedRange, critical for rare cases when the server attempts to fully tuple-decode
an Incomplete Versionstamp in the value portion of the Index Entry instead of lazy evaluation. We believe this could
cause Error 2042: "The value cannot be parsed as a tuple" in rare cases.

## v0.7.3 (2026-04-06)

### Bug fixes
Expand Down
17 changes: 12 additions & 5 deletions lib/ecto_foundationdb/indexer/default.ex
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ defmodule EctoFoundationDB.Indexer.Default do
# same transaction. So, we must choose either the key or the value of the index entry.
# A natural choice is to use the value to have the versionstamp so that
# get_mapped_range works correctly. However, then we lose the ability to manage the index
# on updates and clears. Therefore, we must put the versionstamp in the index_key and
# on updates and clears. Therefore, we must put the versionstamp in the index_key,
# which forces our mapper to inspect both the key and value to extract the pk.
#
# This means that the value portion of the index kv will always be written with an
Expand Down Expand Up @@ -393,18 +393,25 @@ defmodule EctoFoundationDB.Indexer.Default do
"""
end

# See key-value design in get_index_entry
defp mapper(tenant, idx_len) do
# (#93) We choose to extract all items from the Key, because when Versionstamps are in play,
# the Value is not actually a valid tuple. It contains the incomplete versionstamp, which
# which has a short trailing portion. If FDB allowed us to set_versionstamp_key_and_value
# then we'd be free to define the mapper on either the key or the value. But since we are
# forced to pick set_versionstamped_key, which must also extract the tuple items from the
# Key.
#
# Also see key-value design in get_index_entry and set_index_entry for more details.
offset_fun = fn offset ->
[
# prefix
"{V[#{offset}]}",
"{K[#{offset}]}",

# source
"{V[#{offset + 1}]}",
"{K[#{offset + 1}]}",

# namespace
"{V[#{offset + 2}]}",
"d",

# pk: get it from the index_key because the versionstamp lives there, not in the value
"{K[#{offset + 5 + idx_len}]}",
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule EctoFoundationdb.MixProject do
def project do
[
app: :ecto_foundationdb,
version: "0.7.3",
version: "0.7.4",
description: "FoundationDB adapter for Ecto",
elixir: "~> 1.15",
start_permanent: Mix.env() == :prod,
Expand Down
Loading