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

Websockets Tutorial #663

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Websockets Tutorial #663

wants to merge 3 commits into from

Conversation

eladcon
Copy link

@eladcon eladcon commented Oct 23, 2023

Docs updates should not be submitted in this repository

Our doc site content is being automatically updated from Wing repository docs folder.

Please submit any changes to the docs as a PR here

@vercel
Copy link

vercel bot commented Oct 23, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
wing-docs ❌ Failed (Inspect) Oct 29, 2023 3:15pm

@eladcon eladcon marked this pull request as ready for review October 24, 2023 11:01
@@ -0,0 +1,484 @@
---
title: "Builing a Websockets app with Winglang"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title: "Builing a Websockets app with Winglang"
title: "Building a WebSocket app with Winglang"

@@ -0,0 +1,484 @@
---
title: "Builing a Websockets app with Winglang"
description: A step by step Winglang tutorial for builing serverless websocket applications
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: A step by step Winglang tutorial for builing serverless websocket applications
description: A step by step tutorial for building serverless WebSocket applications in Winglang

Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome stuff...

hide_table_of_contents: true
---

In this tutorial we're going to use Winglang to build a web based application powered by websockets. We will cover how to build basic resources in Winglang with a special focus on serverless cloud abilities. We will learn how to integrate JS code into our Wing app and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this tutorial we're going to use Winglang to build a web based application powered by websockets. We will cover how to build basic resources in Winglang with a special focus on serverless cloud abilities. We will learn how to integrate JS code into our Wing app and
In this tutorial we're going to use [Winglang](https://winglang.io) to build a web based application powered by [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). We will cover how to build basic user-defined resources in Winglang with a special focus on serverless cloud abilities. We will learn how to integrate JavaScript code into our Wing app and

In this tutorial we're going to use Winglang to build a web based application powered by websockets. We will cover how to build basic resources in Winglang with a special focus on serverless cloud abilities. We will learn how to integrate JS code into our Wing app and
how to test our application end-to-end for our local environment as well as our cloud.

### A Websocket server
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### A Websocket server
### A WebSocket server

Fix throughout the post


Since Websockets are still not supported natively in Winglang, we will create a websockets resource ourselves. This will allow us to abstract the cloud and its underlying resources, so all of our server logic will be the same no matter where it will run.

First thing first, let's define a wing interface that could help represent websockets support:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
First thing first, let's define a wing interface that could help represent websockets support:
First things first, let's define an interface that could help represent WebSockets support:


Now let's implement our interface for a local experience. By developing locally, we wouldn't have to wait for long deployment cycles, our tests will run faster and we will have a better debugging experience.

Since we can't start a websocket server directly from wing yet, we can use JS code instead:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would frame this a bit differently:

Suggested change
Since we can't start a websocket server directly from wing yet, we can use JS code instead:
We will use the [ws](https://www.npmjs.com/package/ws) library in order to implement
out WebSockets server.
Wing can interact with any JavaScript library through [`extern`](https://www.winglang.io/docs/language-reference#52-javascript) methods. So let's write start by writing our JavaScript code to implement some of this API:

const wss = new WebSocketServer({ port });
global.wss = wss;

wss.on('connection', function connection(ws) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need the name?

Suggested change
wss.on('connection', function connection(ws) {
wss.on('connection', ws => {

Now when someone will create a new `WebSocketApi_aws`, it will also create a new AWS API Gateway. To attach an API Gateway Integration, Route and Lambda to this Gateway, we'll implement a new method called `createRoute`. This method accepts a `cloud.Function` along with route details and will create the additional API Gateway cloud resources:

```js
createRoute(handler: cloud.Function, routeName: str, routeKey: str) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not super clear under which class this method is. Maybe something like:

pub class WebSocketApi_aws {
  // ...

  createRoute(...
}

pub onLift(host: std.IInflightHost, ops: Array<str>) {
if let host = aws.Function.from(host) {
if ops.contains("send") {
host.addPolicyStatements(aws.PolicyStatement {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
host.addPolicyStatements(aws.PolicyStatement {
host.addPolicyStatements({

}
```

#### A proxy for the abstraction
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### A proxy for the abstraction
#### An abstraction dispatch


In this tutorial we have created a full Websockets server ready to be deployed on the cloud but can also be debugged and tested locally. We created all of our infrastructure straight from our code which also seamlessly include our custom logic. See the full code here https://github.com/eladcon/wing-websockets.

Winglang is stil growing as a language and it's eco system is developing rapidly. Make sure to follow us on https://winglang.io.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Winglang is stil growing as a language and it's eco system is developing rapidly. Make sure to follow us on https://winglang.io.
Winglang is still growing as a language and it's ecosystem is developing rapidly. Make sure to follow us on https://winglang.io.

connectionId: str,
message: str,
): inflight(): void;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend consolidating all extern calls to ws under a single module called ws.w with a Util class. This has the undocumented side effect that you can call the static methods without the class name. It also makes it cleaner from a code organization perspective.

Something like this:

ws.w

pub class Util {
  extern "./ws.js" pub static inflight startServer(
    connectFn: inflight (str): void,
    disconnectFn: inflight (str): void,
    onmessageFn: inflight (str, str): void
  ): StartWebSocketApiResult;

  extern "./ws.js" pub static inflight sendMessage(
    connectionId: str,
    message: str,
  ): inflight(): void;
}

Then:

main.w:

bring "./ws.w" as ws;

ws.startServer(...)

Yes, it works...

}
```

For each WS event - a client connected, a client disconnected and a message recieved - we are configuring an inflight handler which will accept a connection ID (and additional message) and will allow us to react with our respective application logic. Additionaly, we will implement sending a message to a specific connection. Finally, we want to know the server URL, so client could connect.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For each WS event - a client connected, a client disconnected and a message recieved - we are configuring an inflight handler which will accept a connection ID (and additional message) and will allow us to react with our respective application logic. Additionaly, we will implement sending a message to a specific connection. Finally, we want to know the server URL, so client could connect.
For each WS event - a client connected, a client disconnected and a message recieved - we are configuring an inflight handler which will accept a connection ID (and additional message) and will allow us to react with our respective application logic. Additionally, we will implement sending a message to a specific connection. Finally, we want to know the server URL, so client could connect.

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

Successfully merging this pull request may close these issues.

4 participants