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

Do Rust tour split #224

Merged
merged 5 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions tutorials/tour-of-restate-go/part2/checkoutservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import restate "github.com/restatedev/sdk-go"

// <start_checkout>
type CheckoutService struct{}

type CheckoutRequest struct {
Expand All @@ -13,5 +12,3 @@ type CheckoutRequest struct {
func (CheckoutService) Handle(ctx restate.Context, request CheckoutRequest) (bool, error) {
return true, nil
}

// <end_checkout>
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ class Order(TypedDict):
checkout = Service("CheckoutService")


# <start_checkout>
@checkout.handler()
async def handle(ctx: ObjectContext, order: Order) -> bool:
return True
# <end_checkout>
6 changes: 0 additions & 6 deletions tutorials/tour-of-restate-python/tour/part2/ticket_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,16 @@
ticket = VirtualObject("TicketObject")


# <start_reserve>
@ticket.handler()
async def reserve(ctx: ObjectContext) -> bool:
return True
# <end_reserve>


# <start_unreserve>
@ticket.handler()
async def unreserve(ctx: ObjectContext):
return
# <end_unreserve>


# <start_mark_as_sold>
@ticket.handler("markAsSold")
async def mark_as_sold(ctx: ObjectContext):
return
# <end_mark_as_sold>
3 changes: 1 addition & 2 deletions tutorials/tour-of-restate-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 21 additions & 2 deletions tutorials/tour-of-restate-rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ edition = "2021"
restate-sdk = "0.3"
tokio = { version = "1", features = ["full"] }
tracing-subscriber = "0.3"
rand = "0.8.5"
anyhow = "1.0.86"
serde = { version = "1", features = ["derive"] }
log = "0.4.22"

[[bin]]
name = "app"
path = "src/app/main.rs"

[[bin]]
name = "part1"
path = "src/part1/main.rs"

[[bin]]
name = "part2"
path = "src/part2/main.rs"

[[bin]]
name = "part3"
path = "src/part3/main.rs"

[[bin]]
name = "part4"
path = "src/part4/main.rs"
35 changes: 35 additions & 0 deletions tutorials/tour-of-restate-rust/src/app/cart_object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use restate_sdk::prelude::*;

#[restate_sdk::object]
pub(crate) trait CartObject {
#[name = "addTicket"]
async fn add_ticket(ticket_id: String) -> Result<bool, HandlerError>;
async fn checkout() -> Result<bool, HandlerError>;
#[name = "expireTicket"]
async fn expire_ticket(ticket_id: String) -> Result<(), HandlerError>;
}

pub struct CartObjectImpl;

impl CartObject for CartObjectImpl {
async fn add_ticket(
&self,
_ctx: ObjectContext<'_>,
_ticket_id: String,
) -> Result<bool, HandlerError> {
Ok(true)
}

async fn checkout(&self, _ctx: ObjectContext<'_>) -> Result<bool, HandlerError> {
Ok(true)
}

async fn expire_ticket(
&self,
_ctx: ObjectContext<'_>,
_ticket_id: String,
) -> Result<(), HandlerError> {

Ok(())
}
}
27 changes: 27 additions & 0 deletions tutorials/tour-of-restate-rust/src/app/checkout_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use std::collections::HashSet;
use restate_sdk::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct CheckoutRequest {
pub(crate) user_id: String,
pub(crate) tickets: HashSet<String>,
}

#[restate_sdk::service]
pub(crate) trait CheckoutService {
async fn handle(request: Json<CheckoutRequest>) -> Result<bool, HandlerError>;
}

pub struct CheckoutServiceImpl;

impl CheckoutService for CheckoutServiceImpl {
async fn handle(
&self,
_ctx: Context<'_>,
Json(CheckoutRequest { user_id: _, tickets: _ }): Json<CheckoutRequest>,
) -> Result<bool, HandlerError> {
Ok(true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ mod cart_object;
mod checkout_service;
mod ticket_object;

pub mod auxiliary;

use restate_sdk::prelude::*;
use crate::cart_object::CartObject;
use crate::checkout_service::CheckoutService;
use crate::ticket_object::TicketObject;

#[path="../auxiliary/mod.rs"]
mod auxiliary;

#[tokio::main]
async fn main() {
// To enable logging
Expand Down
25 changes: 25 additions & 0 deletions tutorials/tour-of-restate-rust/src/app/ticket_object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use restate_sdk::prelude::*;

#[restate_sdk::object]
pub(crate) trait TicketObject {
async fn reserve() -> Result<bool, HandlerError>;
async fn unreserve() -> Result<(), HandlerError>;
#[name = "markAsSold"]
async fn mark_as_sold() -> Result<(), HandlerError>;
}

pub struct TicketObjectImpl;

impl TicketObject for TicketObjectImpl {
async fn reserve(&self, _ctx: ObjectContext<'_>) -> Result<bool, HandlerError> {
Ok(true)
}

async fn unreserve(&self, _ctx: ObjectContext<'_>) -> Result<(), HandlerError> {
Ok(())
}

async fn mark_as_sold(&self, _ctx: ObjectContext<'_>) -> Result<(), HandlerError> {
Ok(())
}
}
19 changes: 5 additions & 14 deletions tutorials/tour-of-restate-rust/src/auxiliary/email_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,27 @@
// 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/
#![allow(unused)]

use log::info;
use restate_sdk::errors::HandlerError;

pub struct EmailClient;

impl EmailClient {
pub fn new() -> Self {
EmailClient
}

pub async fn notify_user_of_payment_success(
&self,
user_id: &str,
) -> Result<bool, HandlerError> {
println!("Notifying user {} of payment success", user_id);
info!("Notifying user {} of payment success", user_id);
// send the email
Ok(true)
}

pub async fn notify_user_of_payment_failure(
&self,
user_id: &str,
) -> Result<bool, HandlerError> {
println!("Notifying user {} of payment failure", user_id);
info!("Notifying user {} of payment failure", user_id);
// send the email
Ok(false)
}
}

impl Default for EmailClient {
fn default() -> Self {
Self::new()
}
}
2 changes: 1 addition & 1 deletion tutorials/tour-of-restate-rust/src/auxiliary/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod email_client;
pub mod payment_client;
pub mod ticket_status;
pub mod ticket_status;
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
// 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/
#![allow(unused)]
use restate_sdk::errors::HandlerError;
use std::sync::atomic::{AtomicI32, Ordering};
use std::sync::Arc;
use log::info;

pub struct PaymentClient {
attempts: Arc<AtomicI32>,
Expand All @@ -22,7 +24,7 @@ impl PaymentClient {
}

pub async fn call(&self, idempotency_key: &str, amount: f64) -> Result<bool, HandlerError> {
println!(
info!(
"Payment call succeeded for idempotency key {} and amount {}",
idempotency_key, amount
);
Expand All @@ -37,14 +39,14 @@ impl PaymentClient {
) -> Result<bool, HandlerError> {
let attempt = self.attempts.load(Ordering::SeqCst);
if attempt >= 2 {
println!(
info!(
"Payment call succeeded for idempotency key {} and amount {}",
idempotency_key, amount
);
self.attempts.store(0, Ordering::SeqCst);
Ok(true)
} else {
println!(
info!(
"Payment call failed for idempotency key {} and amount {}. Retrying...",
idempotency_key, amount
);
Expand Down
65 changes: 65 additions & 0 deletions tutorials/tour-of-restate-rust/src/part1/cart_object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::collections::HashSet;
use crate::checkout_service::{CheckoutRequest, CheckoutServiceClient};
use crate::ticket_object::TicketObjectClient;
use restate_sdk::prelude::*;

#[restate_sdk::object]
pub(crate) trait CartObject {
#[name = "addTicket"]
async fn add_ticket(ticket_id: String) -> Result<bool, HandlerError>;
async fn checkout() -> Result<bool, HandlerError>;
#[name = "expireTicket"]
async fn expire_ticket(ticket_id: String) -> Result<(), HandlerError>;
}

pub struct CartObjectImpl;

impl CartObject for CartObjectImpl {
// <start_add_ticket>
async fn add_ticket(
&self,
ctx: ObjectContext<'_>,
ticket_id: String,
) -> Result<bool, HandlerError> {
// !mark(1:5)
let _reservation_success = ctx
.object_client::<TicketObjectClient>(ticket_id.clone())
.reserve()
.call()
.await?;

Ok(true)
}
// <end_add_ticket>

// <start_checkout>
async fn checkout(&self, ctx: ObjectContext<'_>) -> Result<bool, HandlerError> {
// !mark(1:8)
let success = ctx
.service_client::<CheckoutServiceClient>()
.handle(Json(CheckoutRequest {
user_id: ctx.key().parse()?,
tickets: HashSet::from([String::from("seat2B")]),
}))
.call()
.await?;

Ok(success)
}
// <end_checkout>

// <start_expire_ticket>
async fn expire_ticket(
&self,
ctx: ObjectContext<'_>,
ticket_id: String,
) -> Result<(), HandlerError> {
// !mark(1:3)
ctx.object_client::<TicketObjectClient>(ticket_id)
.unreserve()
.send();

Ok(())
}
// <end_expire_ticket>
}
29 changes: 29 additions & 0 deletions tutorials/tour-of-restate-rust/src/part1/checkout_service.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::collections::HashSet;
use restate_sdk::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct CheckoutRequest {
pub(crate) user_id: String,
pub(crate) tickets: HashSet<String>,
}

// <start_checkout>
#[restate_sdk::service]
pub(crate) trait CheckoutService {
async fn handle(request: Json<CheckoutRequest>) -> Result<bool, HandlerError>;
}

pub struct CheckoutServiceImpl;

impl CheckoutService for CheckoutServiceImpl {
async fn handle(
&self,
_ctx: Context<'_>,
Json(CheckoutRequest { user_id: _, tickets: _ }): Json<CheckoutRequest>,
) -> Result<bool, HandlerError> {
Ok(true)
}
}
// <end_checkout>
26 changes: 26 additions & 0 deletions tutorials/tour-of-restate-rust/src/part1/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
mod cart_object;
mod checkout_service;
mod ticket_object;
#[path = "../auxiliary/mod.rs"]
mod auxiliary;

use restate_sdk::prelude::*;
use crate::cart_object::CartObject;
use crate::checkout_service::CheckoutService;
use crate::ticket_object::TicketObject;

#[tokio::main]
async fn main() {
// To enable logging
tracing_subscriber::fmt::init();

HttpServer::new(
Endpoint::builder()
.bind(cart_object::CartObjectImpl.serve())
.bind(checkout_service::CheckoutServiceImpl.serve())
.bind(ticket_object::TicketObjectImpl.serve())
.build(),
)
.listen_and_serve("0.0.0.0:9080".parse().unwrap())
.await;
}
Loading
Loading