Amarula.Protocol.Signal.DeviceListCache (amarula v0.1.0)
View SourcePer-user cache of a contact's device list, ported from Baileys'
userDevicesCache (the getUSyncDevices cache). Lets a send skip the USync
round-trip when we already know a user's devices.
Keyed by JID user (the part before @), value = the list of device maps
%{user, device, server, jid} that USync.Devices.extract/4 produces.
Persistence goes through the pluggable Amarula.Storage seam (:device_list
namespace, keyed by user), scoped to the connection conn (Amarula.Conn).
Entries carry a stored-at timestamp and expire after @ttl_ms so a stale
device list is eventually re-fetched even without a server staleness signal
(Baileys uses an LRU with a TTL; phash-based invalidation is disabled
upstream). TTL is enforced here in the cache, not in the storage adapter.
Summary
Functions
Drop a user's cached device list (e.g. on a device-list-change notification).
Fetch the cached device list for a JID (or user string). Returns nil on a
miss or when the entry has expired.
Look up several users at once. Returns {hits, misses} where hits is a
user => devices map and misses is the list of users with no fresh entry.
Store devices for user (overwriting any prior entry). devices is the
full list for that user; pass the user JID or bare user string.
Store device lists for many users at once. by_user is user => devices.
Returns :ok.
Types
@type device() :: %{ user: String.t(), device: non_neg_integer(), server: String.t(), jid: String.t() }
Functions
@spec delete(Amarula.Conn.t(), String.t()) :: :ok
Drop a user's cached device list (e.g. on a device-list-change notification).
@spec get(Amarula.Conn.t(), String.t()) :: [device()] | nil
Fetch the cached device list for a JID (or user string). Returns nil on a
miss or when the entry has expired.
@spec get_many(Amarula.Conn.t(), [String.t()]) :: {%{required(String.t()) => [device()]}, [String.t()]}
Look up several users at once. Returns {hits, misses} where hits is a
user => devices map and misses is the list of users with no fresh entry.
@spec put(Amarula.Conn.t(), String.t(), [device()]) :: :ok | {:error, term()}
Store devices for user (overwriting any prior entry). devices is the
full list for that user; pass the user JID or bare user string.
@spec put_many(Amarula.Conn.t(), %{required(String.t()) => [device()]}) :: :ok
Store device lists for many users at once. by_user is user => devices.
Returns :ok.