1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.FedSockets.FetchRegistry do
7 The FetchRegistry acts as a broker for fetch requests and return values.
8 This allows calling processes to block while waiting for a reply.
9 It doesn't impose it's own process instead using `Cachex` to handle fetches in process, allowing
10 multi threaded processes to avoid bottlenecking.
12 Normally outside modules will have no need to call or use the FetchRegistry themselves.
14 The `Cachex` parameters can be controlled from the config. Since exact timeout intervals
15 aren't necessary the following settings are used by default:
17 config :pleroma, :fed_sockets,
26 defmodule FetchRegistryData do
38 @fetches :fed_socket_fetches
41 Registers a json request wth the FetchRegistry and returns the identifying UUID.
43 def register_fetch(json) do
44 %FetchRegistryData{uuid: uuid} =
53 Reports on the status of a Fetch given the identifying UUID.
56 * {:ok, fetched_object} if a fetch has completed
57 * {:error, :waiting} if a fetch is still pending
58 * {:error, other_error} usually :missing to indicate a fetch that has timed out
60 def check_fetch(uuid) do
61 case get_registry_data(uuid) do
62 {:ok, %FetchRegistryData{received_at: nil}} ->
65 {:ok, %FetchRegistryData{} = reg_data} ->
74 Retrieves the response to a fetch given the identifying UUID.
75 The completed fetch will be deleted from the FetchRegistry
78 * {:ok, fetched_object} if a fetch has completed
79 * {:error, :waiting} if a fetch is still pending
80 * {:error, other_error} usually :missing to indicate a fetch that has timed out
82 def pop_fetch(uuid) do
83 case check_fetch(uuid) do
84 {:ok, %FetchRegistryData{received_json: received_json}} ->
85 delete_registry_data(uuid)
94 This is called to register a fetch has returned.
95 It expects the result data along with the UUID that was sent in the request
97 Will return the fetched object or :error
99 def register_fetch_received(uuid, data) do
100 case get_registry_data(uuid) do
101 {:ok, %FetchRegistryData{received_at: nil} = reg_data} ->
103 |> set_fetch_received(data)
104 |> save_registry_data()
106 {:ok, %FetchRegistryData{} = reg_data} ->
107 Logger.warn("tried to add fetched data twice - #{uuid}")
111 Logger.warn("Error adding fetch to registry - #{uuid}")
116 defp new_registry_data(json) do
118 uuid: UUID.generate(),
120 sent_at: :erlang.monotonic_time(:millisecond)
124 defp get_registry_data(origin) do
125 case Cachex.get(@fetches, origin) do
133 {:error, :cache_error}
137 defp set_fetch_received(%FetchRegistryData{} = reg_data, data),
138 do: %FetchRegistryData{
140 | received_at: :erlang.monotonic_time(:millisecond),
144 defp save_registry_data(%FetchRegistryData{uuid: uuid} = reg_data) do
145 {:ok, true} = Cachex.put(@fetches, uuid, reg_data)
149 defp delete_registry_data(origin),
150 do: {:ok, true} = Cachex.del(@fetches, origin)