Skip to content

Commit

Permalink
Merge pull request #100 from VictorGaiva/fix/channel-process-gc
Browse files Browse the repository at this point in the history
Adds an option to periodically run `:erlang.garbage_collect` on both the Channel and Transport processes
  • Loading branch information
benwilson512 authored Dec 14, 2023
2 parents e0c7b30 + cdf3498 commit 6ae2785
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
20 changes: 17 additions & 3 deletions lib/absinthe/phoenix/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule Absinthe.Phoenix.Channel do
def join("__absinthe__:control", _, socket) do
schema = socket.assigns[:__absinthe_schema__]
pipeline = socket.assigns[:__absinthe_pipeline__]
gc_interval = socket.assigns[:__absinthe_gc_interval__]

absinthe_config = Map.get(socket.assigns, :absinthe, %{})

Expand All @@ -32,7 +33,13 @@ defmodule Absinthe.Phoenix.Channel do
|> Map.update(:schema, schema, & &1)

absinthe_config =
Map.put(absinthe_config, :pipeline, pipeline || {__MODULE__, :default_pipeline})
absinthe_config
|> Map.put(:pipeline, pipeline || {__MODULE__, :default_pipeline})
|> Map.put(:gc_interval, gc_interval)

unless gc_interval == nil do
Process.send_after(self(), :gc, gc_interval)
end

socket = socket |> assign(:absinthe, absinthe_config)
{:ok, socket}
Expand Down Expand Up @@ -142,7 +149,14 @@ defmodule Absinthe.Phoenix.Channel do
|> Absinthe.Pipeline.for_document(options)
end

def handle_info(_, state) do
{:noreply, state}
def handle_info(:gc, socket) do
:erlang.garbage_collect()
:erlang.garbage_collect(socket.transport_pid)
Process.send_after(self(), :gc, socket.assigns.absinthe.gc_interval)
{:noreply, socket}
end

def handle_info(_, socket) do
{:noreply, socket}
end
end
16 changes: 15 additions & 1 deletion lib/absinthe/phoenix/socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ defmodule Absinthe.Phoenix.Socket do
## Phoenix 1.2
If you're on Phoenix 1.2 see `put_schema/2`.
## Garbage Collection
In some workloads, the Channel Process responsible for handling [subscriptions may accumulate
some gargage](https://elixirforum.com/t/why-does-garbage-collection-not-work-as-intended/50613/2), that is not being collected by the Erlang VM. A workaround for this is to instruct
the process to periodically tell the VM to collect its garbage. This can be done by setting the
`gc_interval`.
use Absinthe.Phoenix.Socket,
schema: MyApp.Web.Schema,
gc_interval: 10_000
"""

defmacro __using__(opts) do
Expand All @@ -37,14 +49,16 @@ defmodule Absinthe.Phoenix.Socket do

schema = Keyword.get(opts, :schema)
pipeline = Keyword.get(opts, :pipeline)
gc_interval = Keyword.get(opts, :gc_interval)

quote do
channel(
"__absinthe__:*",
Absinthe.Phoenix.Channel,
assigns: %{
__absinthe_schema__: unquote(schema),
__absinthe_pipeline__: unquote(pipeline)
__absinthe_pipeline__: unquote(pipeline),
__absinthe_gc_interval__: unquote(gc_interval)
}
)
end
Expand Down

0 comments on commit 6ae2785

Please sign in to comment.