Skip to content

Commit

Permalink
New quickstart (#214)
Browse files Browse the repository at this point in the history
* new greeter template to show durable execution

* new greeter template for Java templates

* new greeter template for Kotlin templates

* new greeter template for Go templates

* new greeter template for Python templates

* new greeter template for Rust templates

* Fix comments

* Add ghost to error messages

* Fix wrong imports in templates

* Remove licenses of templates because they are shown as code snippets in the docs

* Make code snippets more concise

* Use pydantic for Python template

* throw runtime exception in java templates

* Fix import in TS deno template

* Kotlin template: Rename to utils.kt

* Upgrade go version

* Fix rust template

* Fix Java templates issues

* Fix cloudflare workers template

* Fix package name quarkus template

* Fix Rust shuttle template

* Clean imports
  • Loading branch information
gvdongen authored Nov 22, 2024
1 parent 28ded7c commit d5bb855
Show file tree
Hide file tree
Showing 42 changed files with 551 additions and 172 deletions.
35 changes: 21 additions & 14 deletions templates/bun/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { Context, endpoint, service } from "@restatedev/restate-sdk/fetch";
import * as restate from "@restatedev/restate-sdk/fetch";
import {sendNotification, sendReminder} from "./utils";

// Template of a Restate service and handler
//
// Have a look at the TS QuickStart: https://docs.restate.dev/get_started/quickstart?sdk=ts
//
const handler = restate
.endpoint()
.bind(
restate.service({
name: "Greeter",
handlers: {
greet: async (ctx: restate.Context, name: string) => {

const greeter = service({
name: "Greeter",
handlers: {
greet: async (ctx: Context, greeting: string) => {
return `${greeting}!`;
},
},
});
// Durably execute a set of steps; resilient against failures
const greetingId = ctx.rand.uuidv4();
await ctx.run(() => sendNotification(greetingId, name));
await ctx.sleep(1000);
await ctx.run(() => sendReminder(greetingId));

const handler = endpoint().bind(greeter).handler();
// Respond to caller
return `You said hi to ${name}!`;
},
},
}),
)
.handler();

const server = Bun.serve({
port: 9080,
Expand Down
19 changes: 19 additions & 0 deletions templates/bun/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

// You can remove this file.
// It's only purpose is providing stubs for the template.

export function sendNotification(greetingId: string, name: string) {
if (Math.random() < 0.5) { // 50% chance of failure
console.error(`👻 Failed to send notification: ${greetingId} - ${name}`);
throw new Error(`Failed to send notification ${greetingId} - ${name}`);
}
console.log(`Notification sent: ${greetingId} - ${name}`);
}

export function sendReminder(greetingId: string) {
if (Math.random() < 0.5) { // 50% chance of failure
console.error(`👻 Failed to send reminder: ${greetingId}`);
throw new Error(`Failed to send reminder: ${greetingId}`);
}
console.log(`Reminder sent: ${greetingId}`);
}
36 changes: 21 additions & 15 deletions templates/cloudflare-worker/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import { Context, endpoint, service } from "@restatedev/restate-sdk-cloudflare-workers/fetch";
import * as restate from "@restatedev/restate-sdk-cloudflare-workers/fetch";
import { sendNotification, sendReminder } from "./utils.js";

// Template of a Restate service and handler
//
// Have a look at the TS QuickStart: https://docs.restate.dev/get_started/quickstart?sdk=ts
//
export default restate
.endpoint()
.bind(
restate.service({
name: "greeter",
handlers: {
greet: async (ctx: restate.Context, name: string) => {
// Durably execute a set of steps; resilient against failures
const greetingId = ctx.rand.uuidv4();
await ctx.run(() => sendNotification(greetingId, name));
await ctx.sleep(1000);
await ctx.run(() => sendReminder(greetingId));

const greeter = service({
name: "greeter",
handlers: {
greet: async (ctx: Context, greeting: string) => {
return `${greeting}!`;
},
},
});

export default endpoint().bind(greeter).handler();
// Respond to caller
return `You said hi to ${name}!`;
},
},
}),
)
.handler();
20 changes: 20 additions & 0 deletions templates/cloudflare-worker/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// You can remove this file.
// It's only purpose is providing stubs for the template.

export function sendNotification(greetingId: string, name: string) {
if (Math.random() < 0.5) {
// 50% chance of failure
console.error(`👻 Failed to send notification: ${greetingId} - ${name}`);
throw new Error(`Failed to send notification ${greetingId} - ${name}`);
}
console.log(`Notification sent: ${greetingId} - ${name}`);
}

export function sendReminder(greetingId: string) {
if (Math.random() < 0.5) {
// 50% chance of failure
console.error(`👻 Failed to send reminder: ${greetingId}`);
throw new Error(`Failed to send reminder: ${greetingId}`);
}
console.log(`Reminder sent: ${greetingId}`);
}
41 changes: 22 additions & 19 deletions templates/deno/main.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import {
Context,
endpoint,
service,
} from "npm:@restatedev/restate-sdk@^1.4.0/fetch";
import * as restate from "npm:@restatedev/restate-sdk/fetch";
import { sendNotification, sendReminder } from "./utils.ts";

// Template of a Restate service and handler
//
// Have a look at the TS QuickStart: https://docs.restate.dev/get_started/quickstart?sdk=ts
//
const handler = restate
.endpoint()
.bind(
restate.service({
name: "Greeter",
handlers: {
greet: async (ctx: restate.Context, name: string) => {
// Durably execute a set of steps; resilient against failures
const greetingId = ctx.rand.uuidv4();
await ctx.run(() => sendNotification(greetingId, name));
await ctx.sleep(1000);
await ctx.run(() => sendReminder(greetingId));

const greeter = service({
name: "Greeter",
handlers: {
greet: async (ctx: Context, greeting: string) => {
return `${greeting}!`;
},
},
});

const handler = endpoint().bind(greeter).bidirectional().handler();
// Respond to caller
return `You said hi to ${name}!`;
},
},
}),
)
.bidirectional()
.handler();

Deno.serve({ port: 9080 }, handler.fetch);
20 changes: 20 additions & 0 deletions templates/deno/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// You can remove this file.
// It's only purpose is providing stubs for the template.

export function sendNotification(greetingId: string, name: string) {
if (Math.random() < 0.5) {
// 50% chance of failure
console.error(`👻 Failed to send notification: ${greetingId} - ${name}`);
throw new Error(`Failed to send notification ${greetingId} - ${name}`);
}
console.log(`Notification sent: ${greetingId} - ${name}`);
}

export function sendReminder(greetingId: string) {
if (Math.random() < 0.5) {
// 50% chance of failure
console.error(`👻 Failed to send reminder: ${greetingId}`);
throw new Error(`Failed to send reminder: ${greetingId}`);
}
console.log(`Reminder sent: ${greetingId}`);
}
7 changes: 6 additions & 1 deletion templates/go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ module github.com/restatedev/examples/templates/go

go 1.22.5

require github.com/restatedev/sdk-go v0.11.0
require github.com/restatedev/sdk-go v0.12.0

require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
Expand Down
21 changes: 15 additions & 6 deletions templates/go/go.sum
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/restatedev/sdk-go v0.11.0 h1:5pN5XSlTxJBWHZEuY0fZPorKU6xncz5CPGnnCChgjxg=
github.com/restatedev/sdk-go v0.11.0/go.mod h1:6gHoU8pyP7YQfFWxKG2u94u/TSGen0qN7BWowWNDw4Y=
github.com/restatedev/sdk-go v0.12.0 h1:M9bdcsHvJALcg27U0s6V7HD1qNVFPh60XhM5H/n2zlQ=
github.com/restatedev/sdk-go v0.12.0/go.mod h1:Xalv67a5uOgGcbz7U1BgZQydCrsmENq2RAeTwTGXHng=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
27 changes: 23 additions & 4 deletions templates/go/greeter.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
package main

import (
"fmt"

restate "github.com/restatedev/sdk-go"
"time"
)

// Greeter is a struct which represents a Restate service; reflection will turn exported methods into service handlers
type Greeter struct{}

func (Greeter) Greet(ctx restate.Context, greeting string) (string, error) {
return fmt.Sprintf("%s!", greeting), nil
func (Greeter) Greet(ctx restate.Context, name string) (string, error) {
// Durably execute a set of steps; resilient against failures
greetingId := restate.Rand(ctx).UUID().String()

if _, err := restate.Run(ctx, func(ctx restate.RunContext) (restate.Void, error) {
return restate.Void{}, SendNotification(greetingId, name)
}); err != nil {
return "", err
}

if err := restate.Sleep(ctx, 1*time.Second); err != nil {
return "", err
}

if _, err := restate.Run(ctx, func(ctx restate.RunContext) (restate.Void, error) {
return restate.Void{}, SendReminder(greetingId)
}); err != nil {
return "", err
}

// Respond to caller
return "You said hi to " + name + "!", nil
}
24 changes: 24 additions & 0 deletions templates/go/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"fmt"
"math/rand"
)

func SendNotification(greetingId string, name string) error {
if rand.Float32() < 0.5 { // 50% chance of failure
fmt.Printf("👻 Failed to send notification: %s - %s\n", greetingId, name)
return fmt.Errorf("failed to send notification: %s - %s", greetingId, name)
}
fmt.Printf("Notification sent: %s - %s\n", greetingId, name)
return nil
}

func SendReminder(greetingId string) error {
if rand.Float32() < 0.5 { // 50% chance of failure
fmt.Printf("👻 Failed to send reminder: %s\n", greetingId)
return fmt.Errorf("failed to send reminder: %s", greetingId)
}
fmt.Printf("Reminder sent: %s\n", greetingId)
return nil
}
6 changes: 6 additions & 0 deletions templates/java-gradle/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ application {

tasks.named<Test>("test") {
useJUnitPlatform()
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
45 changes: 21 additions & 24 deletions templates/java-gradle/src/main/java/my/example/Greeter.java
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
/*
* Copyright (c) 2024 - Restate Software, Inc., Restate GmbH
*
* This file is part of the Restate examples,
* which is released under the MIT license.
*
* You can find a copy of the license in the file LICENSE
* in the root directory of this repository or package or at
* https://github.com/restatedev/examples/
*/

package my.example;

import dev.restate.sdk.Context;
import dev.restate.sdk.annotation.Handler;
import dev.restate.sdk.annotation.Service;
import dev.restate.sdk.http.vertx.RestateHttpEndpointBuilder;

/**
* Template of a Restate service and handler
* Have a look at the Java QuickStart to learn how to run this: https://docs.restate.dev/get_started/quickstart?sdk=java
*/
import java.time.Duration;

import static my.example.Utils.sendNotification;
import static my.example.Utils.sendReminder;

@Service
public class Greeter {

@Handler
public String greet(Context ctx, String greeting) {
return "Hello " + greeting;
}
@Handler
public String greet(Context ctx, String name) {
// Durably execute a set of steps; resilient against failures
String greetingId = ctx.random().nextUUID().toString();
ctx.run(() -> sendNotification(greetingId, name));
ctx.sleep(Duration.ofMillis(1000));
ctx.run(() -> sendReminder(greetingId));

// Respond to caller
return "You said hi to " + name + "!";
}

public static void main(String[] args) {
RestateHttpEndpointBuilder.builder()
.bind(new Greeter())
.buildAndListen();
}
public static void main(String[] args) {
RestateHttpEndpointBuilder.builder()
.bind(new Greeter())
.buildAndListen();
}
}
Loading

0 comments on commit d5bb855

Please sign in to comment.