Skip to content
This repository has been archived by the owner on Apr 25, 2024. It is now read-only.

Introduce Awakeables service #21

Merged
merged 3 commits into from
Aug 18, 2023
Merged

Introduce Awakeables service #21

merged 3 commits into from
Aug 18, 2023

Conversation

slinkydeveloper
Copy link
Contributor

@slinkydeveloper slinkydeveloper commented Aug 14, 2023

Fix #20. Based on restatedev/service-protocol#42.

This will be implemented in a similar fashion to the Ingress service, hence the user can invoke it either using gRPC or using Connect, and with Connect a "special" rule will be applied to parsing:

$ curl -X POST http://<your-restate-runtime-host-port>/dev.restate.Awakeables/Complete -H 'content-type: application/json' -d '{"id": "<some_id>", "result": "this is a string result"}'

Or:

$ curl -X POST http://<your-restate-runtime-host-port>/dev.restate.Awakeables/Complete -H 'content-type: application/json' -d '{"id": "<some_id>", "result": {"field": "this is an object result"}}'

You can also fail the awakeable invoking Fail:

$ curl -X POST http://<your-restate-runtime-host-port>/dev.restate.Awakeables/Fail -H 'content-type: application/json' -d '{"id": "<some_id>", "reason": "Very bad failure!"}'

Copy link
Contributor

@tillrohrmann tillrohrmann left a comment

Choose a reason for hiding this comment

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

Thanks for creating this PR @slinkydeveloper. I had two questions about naming one of the methods and how to complete an awakeable.

dev/restate/services.proto Outdated Show resolved Hide resolved
Comment on lines 50 to 56
// Argument of the invocation.
//
// When executing requests to the ingress using JSON, this field will be parsed as any JSON,
// such as string, object or number.
// When executing requests to the ingress using Protobuf, this field must be bytes.
// The SDK will parse those bytes using the deserializer specified in the user code.
bytes result = 2;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean if I want to complete an awakeable that requires a protobuf encoded value, I cannot use the connect to complete it but need to use grpc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can use protobuf with connect, connect selects the content-type from the content-type header.

Copy link
Contributor Author

@slinkydeveloper slinkydeveloper Aug 15, 2023

Choose a reason for hiding this comment

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

In general we don't have a defined way of what's inside this result. So my idea here is: for JSON users, we just assume this is JSON, for everyone else that wants to send any byte blob in there, sending the request with protobuf is fine, also because JSON doesn't have a built-in "bytes" type representation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Making sure that I understand, would the following work:

sdk:

...
const result = await awakeable;
console.log(result.name);
...
curl --json '{ "id": "...", "result" : {  "name" :  "bob" } }'  < the url >

?

Copy link
Contributor

@igalshilman igalshilman Aug 15, 2023

Choose a reason for hiding this comment

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

edit: the prefix of the message somehow disappeared, seems like GH is not using restate yet :-)

About the approach, I get the idea of using internal service for this, that's pretty clever.
And I suppose that we can take some steps to also make it efficient 👍

Assuming that this is technically doable, What do you think about having a shorter alias for such endpoints?

curl  http://<your-restate-runtime-host-port>/api/awaitable/complete --json '{"id": "<some_id>", "result": { "name" : "bob" } }

or even better

curl  http://<your-restate-runtime-host-port>/api/awaitable/<id>/complete --json '{ "name" : "bob" }'

Copy link
Contributor Author

@slinkydeveloper slinkydeveloper Aug 15, 2023

Choose a reason for hiding this comment

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

For the time being, I suggest to stick with the current API proposal. We probably need to shape a webhooks "story" anyway later with pub/sub. I'm pretty sure the URL size is a problem with webhooks, e.g. with github I tried and I get:

There was an error setting up your hook: Config attribute records value is too long (maximum is 1024 characters) and Config URL must have no more than 1024 characters

1024 characters is not too hard to reach with the current awakeable id.

I have a similar concern about webhook compatibility with Ingress service as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

general my rationale for api design here is that everything should look like any other service,

That's great approach for API design, for sure. In that case tho, this is an implementation detail that this is implemented as a restate service, (and a good one!), so I don't see here an issue of exposing a more useful API endpoint.

This one has the issue that the id tend to be long

The id's are indeed long, but they are around ~150-250 chars (we'd definitely fix that later) does this exceeds the limit + the url (cc: @jackkleeman , how long are our base urls in .cloud ?)
Having such an endpoint will be so great for usability today, even without waiting for the pub sub :-)

The only reason that I will advocate against doing this today, is only if this makes the implementation unnecessarily complicated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is an implementation detail that this is implemented as a restate service

I think I didn't explained myself correctly, my opinion is that this isn't an implementation detail at all, on the contrary it completely fits the Restate "primitives": the user learns that the ingress to interact with Restate services, using either gRPC or Connect. This is one of the first things we teach them in our tutorials. After that, that's it, you don't need to learn anything new if you want to execute one way calls, or complete an awakeable. Perhaps the user will even learn about these services not from the docs, but by using the gRPC reflections, as shown in the tutorials.

The only reason that I will advocate against doing this today, is only if this makes the implementation unnecessarily complicated.

I think this opens some pandora boxes that I would like to keep closed now: naming of the api, styling of the api, how we document it (that is we probably need to develop an openapi documentation for this), where we place this api? same port of the ingress_grpc? or some new server? if it's a new server, where it lives and how does it interact with the rest of the system? if it's the same server of ingress_grpc, then we need to make sure we don't have name clashes e.g. by reserving the api name, etc. Nothing impossible to overcome, but I would be happy to postpone this until we have the concrete use case for that and we can overcome the issues with the id length.

Also, nothing prevents to add a layer at a later point in time to provide the api http://<your-restate-runtime-host-port>/api/awaitable/<id>/complete on top of the built-in services.

Choose a reason for hiding this comment

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

(cc: @jackkleeman , how long are our base urls in .cloud ?)

Depends how long the cluster name is. Its cluster-name.dev.restate.cloud

Copy link
Contributor Author

@slinkydeveloper slinkydeveloper Aug 16, 2023

Choose a reason for hiding this comment

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

Agreed offline for the time being we don't implement the api with the <id> in the path.

@slinkydeveloper slinkydeveloper merged commit 03afce9 into main Aug 18, 2023
2 checks passed
@slinkydeveloper slinkydeveloper deleted the awakeables_service branch August 18, 2023 16:12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Design external API for completing and rejecting awakeables
4 participants