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

Add Cloudflare worker support #766

Closed
jcapogna opened this issue May 18, 2021 · 9 comments · Fixed by #1019
Closed

Add Cloudflare worker support #766

jcapogna opened this issue May 18, 2021 · 9 comments · Fixed by #1019

Comments

@jcapogna
Copy link

jcapogna commented May 18, 2021

I'm aware of the issues in #756 and I am using ably 1.2.3.

After downgrading from latest to 1.2.3, I am experiencing a different problem.

I am getting the following error when running wrangler publish:

Error: Something went wrong! Status: 400 Bad Request, Details {
  "result": null,
  "success": false,
  "errors": [
    {
      "code": 10021,
      "message": "Uncaught Error: Some functionality, such as asynchronous I/O, timeouts, and generating random values, can only be performed while handling a request.\n  at line 34 in nextTick\n  at line 34 in u.requestState\n  at line 34 in t.connect\n  at line 34 in e.connect\n  at line 34 in e\n  at line 22\n  at line 1 in n\n  at line 22\n  at line 1 in n\n  at line 22\n"
    }
  ],
  "messages": []
}

The minimal code required to trigger this error is importing Ably: import * as Ably from "ably"

┆Issue is synchronized with this Jira Task by Unito

@jcapogna
Copy link
Author

I'm now testing the main branch including the webworker support added in #756.

Importing the webworker version of Ably as follows does not trigger this problem anymore:
import * as Ably from 'ably/browser/static/ably-webworker.min'

However, initializing Ably.Realtime does:
const ably = new Ably.Realtime("KEY");

@owenpearson
Copy link
Member

Hi @jcapogna, yeah this is expected; unfortunately the library still won't work in Cloudflare workers. It should now work in a regular webworker context but Cloudflare workers doesn't support XmlHttpRequest (which ably-js uses to make HTTP requests) so we need to do some additional work to support this platform. We'll use this issue to track progress and I hope we can get it resolved for you soon.

@jcapogna
Copy link
Author

Thanks @owenpearson. Do you know if this affects the REST client in addition to the Realtime client?

@owenpearson
Copy link
Member

@jcapogna Yeah it does affect the REST client as well unfortunately. If you don't mind the extra effort you can always use the REST API directly with the fetch API (or any other HTTP client which uses fetch under the hood) in the meantime while we're working on solving this issue.

@jcapogna
Copy link
Author

Good suggestion @owenpearson. Using the REST API might not be too bad for my use case.

@ben-xD
Copy link

ben-xD commented May 29, 2021

I'm able to create token requests by using the Ably Rest client in Cloudflare Workers, you can see my code here: https://github.com/ben-xD/ably-cloudflare-workers

I faced some quirks with cloudflare workers: mainly the handler passed as 2nd argument to addEventListener cannot be an async function. My API is functioning normally and sending token requests back to the client.

Unfortunately, on the free plan CPU execution time is capped to 10ms, and perhaps this is not enough, because the response is not sent back to the client. I confirmed the token is created on the worker by using wrangler tail and viewing the logs though. Do you have a paid Cloudflare account @jcapogna ?

@jcapogna
Copy link
Author

jcapogna commented May 29, 2021

@ben-xD I'm able to do the same. I can use the Ably Rest client in a Cloudflare Worker to invoke ably.auth.createTokenRequest(), which successfully creates a token request.

The Rest client does not work when using it to retrieve channel history. At least in this example.

The code:

import { Rest } from 'ably/promises'

const ably = new Rest({ key: API_KEY });

const channel = ably.channels.get(CHANNEL_NAME);
const messages = await channel.history({ limit: 1 });

Invoking channel.history() results in this error:

TypeError: t.Request is not a function

This seems like the other Cloudflare Worker problem you were having.

I also tried the callback version of the Ably Rest client. That gave me the following error when calling channel.history():

A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's request context have already finished

@ben-xD
Copy link

ben-xD commented May 29, 2021

Do you have an async handler for addEventListener? Your error might be related to this SO question/ answer I posted: https://stackoverflow.com/questions/67756143/cloudflare-worker-times-out-for-the-client-but-all-the-work-completes-and-no-ti/67756144#67756144

@jcapogna
Copy link
Author

jcapogna commented May 30, 2021

I don't think that's the issue.

Here's a repository where I've reduced it down to a minimal example of createTokenRequest working and channel.history failing.

https://github.com/jcapogna/ably-cloudflare-worker-example/blob/master/src/handler.ts

Note that I'm using ably-js 1.2.4. The latest version gave me other errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants