Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bandit intercepting liveview send/2 messages #141

Closed
ringofhealth opened this issue May 7, 2023 · 4 comments
Closed

Bandit intercepting liveview send/2 messages #141

ringofhealth opened this issue May 7, 2023 · 4 comments

Comments

@ringofhealth
Copy link

Hi again!

in our app, we are using liveview, and we are using send/2 and handl_info in :liveview

after switch to bandit, we been noticing that bandit is intercepting the handle_info call within the liveview

[error] GenServer #PID<0.5234.0> terminating
** (FunctionClauseError) no function clause matching in Bandit.HTTP1.Handler.handle_info/2
    (bandit 1.0.0-pre.3) lib/thousand_island/handler.ex:5: Bandit.HTTP1.Handler.handle_info({:update_user_view_count, "21691d84-2656-4556-9b02-f87c3f94bbbd"}, {%ThousandIsland.Socket{socket: #Port<0.216>, transport_module: ThousandIsland.Transports.TCP, read_timeout: 60000, span: %ThousandIsland.Telemetry{span_name: :connection, telemetry_span_context: #Reference<0.2582905735.3298820105.108121>, start_time: -576455428605852008, start_metadata: %{parent_telemetry_span_context: #Reference<0.2582905735.3298820098.52671>, remote_address: {127, 0, 0, 1}, remote_port: 56410, telemetry_span_context: #Reference<0.2582905735.3298820105.108121>}}}, %{handler_module: Bandit.HTTP1.Handler, http_1_enabled: true, http_2_enabled: true, opts: %{http_1: [], http_2: [], websocket: []}, plug: {Phoenix.Endpoint.SyncCodeReloadPlug, {HelioWeb.Endpoint, []}}, requests_processed: 10, websocket_enabled: true}})

here is how the code is being called in our liveview

  def mount(
        %{"id" => id},
        _session,
        %{assigns: %{current_user: current_user}} = socket
      ) do
    user = Accounts.get_by_username!(id)
    send(self(), {:update_user_view_count, user.id})

    {:ok,
     socket}
  end

  @impl true
  def handle_info({:update_user_view_count, user_id}, socket) do
    # Posts.update_post_field_count({:view, post_id})
    Helio.Posts.BatchCounter.Supervisor.increment_user({:view, user_id})

    {:noreply, socket}
  end

any guidance is appreciated

@mtrudel
Copy link
Owner

mtrudel commented May 7, 2023

Is this a websocket or long poll based liveview?

@moogle19
Copy link
Contributor

moogle19 commented May 8, 2023

Try it like this:

  def mount(
        %{"id" => id},
        _session,
        %{assigns: %{current_user: current_user}} = socket
      ) do
    user = Accounts.get_by_username!(id)

    if connected?(socket), do: send(self(), {:update_user_view_count, user.id})

    {:ok,
     socket}
  end

If the LiveView isn't connected yet, your self() will return the Bandit.DelegatingHandler and not your LiveView.
(The message will still be send to your LiveView so your implementation will work, but the send will be called twice)

@ringofhealth
Copy link
Author

Is this a websocket or long poll based liveview?

This is websocket

Try it like this:

  def mount(
        %{"id" => id},
        _session,
        %{assigns: %{current_user: current_user}} = socket
      ) do
    user = Accounts.get_by_username!(id)

    if connected?(socket), do: send(self(), {:update_user_view_count, user.id})

    {:ok,
     socket}
  end

If the LiveView isn't connected yet, your self() will return the Bandit.DelegatingHandler and not your LiveView. (The message will still be send to your LiveView so your implementation will work, but the send will be called twice)

will try this and report back! thank!

@mtrudel
Copy link
Owner

mtrudel commented May 8, 2023

See https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#connected?/1 for docs on this; I think this ought to be more prominent in the live view docs (or maybe even a explicit flag that gets passed to mount) as it's an easy point of confusion.

Closing since I'm 99% sure that @moogle19's advice will work. If not, feel free to reopen!

@mtrudel mtrudel closed this as completed May 8, 2023
paulswartz added a commit to mbta/api that referenced this issue Jan 16, 2024
Related to mtrudel/bandit#141, we get into
this situation when we close the connection before truly entering the
hibernate loop. Instead, we close/unsubscribe directly, and return the
conn immediately.

Sample error from `api-prod` (truncated):
```
Bandit.HTTP1.Handler #PID<0.5319.7> received unexpected message in
handle_info/2: {:close, <conn>}
```
paulswartz added a commit to mbta/api that referenced this issue Jan 16, 2024
Related to mtrudel/bandit#141, we get into
this situation when we close the connection before truly entering the
hibernate loop. Instead, we close/unsubscribe directly, and return the
conn immediately.

Sample error from `api-prod` (truncated):
```
Bandit.HTTP1.Handler #PID<0.5319.7> received unexpected message in
handle_info/2: {:close, <conn>}
```
paulswartz added a commit to mbta/api that referenced this issue Jan 17, 2024
Related to mtrudel/bandit#141, we get into
this situation when we close the connection before truly entering the
hibernate loop. Instead, we close/unsubscribe directly, and return the
conn immediately.

Sample error from `api-prod` (truncated):
```
Bandit.HTTP1.Handler #PID<0.5319.7> received unexpected message in
handle_info/2: {:close, <conn>}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants