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

Experimental functions._invokeWithStreamedResponse never yields data #523

Closed
kirkbyo opened this issue Sep 5, 2024 · 1 comment · Fixed by #525
Closed

Experimental functions._invokeWithStreamedResponse never yields data #523

kirkbyo opened this issue Sep 5, 2024 · 1 comment · Fixed by #525
Labels
bug Something isn't working

Comments

@kirkbyo
Copy link

kirkbyo commented Sep 5, 2024

Bug report

Describe the bug

When utilizing the experimental functions. _invokeWithStreamedResponse method (introduced in #346), the returned AsyncThrowingStream never yields any data to the consumer.

let events = supabase.functions._invokeWithStreamedResponse("some-sse-edge-function", options: options)
for try await data in events {
   // never executed
}

To Reproduce

Initialize _invokeWithStreamedResponse with an edge-function configured to send a text stream (e.g. the Deno SSE template should suffice).

Expected behavior

As bytes are decoded from the underlying NSURLSession they are yielded to the consumer.

System information

  • OS: macOS 14.4.1
  • Version of supabase-swift: 2.13.2
  • iOS version: 17.0.1

Additional context

The current implementation of _invokeWithStreamedResponse creates a session.dataTask with a callback:

let task = session.dataTask(with: urlRequest) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse else {
continuation.finish(throwing: URLError(.badServerResponse))
return
}
guard 200 ..< 300 ~= httpResponse.statusCode else {
let error = FunctionsError.httpError(code: httpResponse.statusCode, data: data ?? Data())
continuation.finish(throwing: error)
return
}
let isRelayError = httpResponse.value(forHTTPHeaderField: "x-relay-error") == "true"
if isRelayError {
continuation.finish(throwing: FunctionsError.relayError)
}
}

however, it is also specifying a URLSession delegate which is responsible for yielding data:

let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)

According to the docs, if a dataTask is specified with a callback, then the delegate is never used, which would explain why values are never yielded:

By using the completion handler, the task bypasses calls to delegate methods for response and data delivery, and instead provides any resulting NSData, URLResponse, and NSError objects inside the completion handler. Delegate methods for handling authentication challenges, however, are still called.

Patching the library to no longer use the callback resolved my issue: kirkbyo@70959a3

@kirkbyo kirkbyo added the bug Something isn't working label Sep 5, 2024
@grdsdev
Copy link
Collaborator

grdsdev commented Sep 6, 2024

Thanks for reporting @kirkbyo

Feel free to open a PR with your fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants