Skip to content

Commit

Permalink
Adapted event logic, mutations, datatypes and OrderItem creation
Browse files Browse the repository at this point in the history
  • Loading branch information
legendofa committed Feb 20, 2024
1 parent f0af340 commit 39b3ef7
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 132 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ tonic = "0.8"
json = "0.12.4"
log = "0.4.20"
simple_logger = "4.3.3"
serde_json = "1.0.113"
serde_json = "1.0.113"
62 changes: 45 additions & 17 deletions src/foreign_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ use bson::{doc, Bson, Uuid};
use serde::{Deserialize, Serialize};
use std::{cmp::Ordering, hash::Hash};

use crate::http_event_service::ProductVariantVersionEventData;

/// Foreign type of a product variant.
#[derive(Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Copy, Clone, SimpleObject)]
#[graphql(unresolvable)]
pub struct ProductVariantVersion {
/// UUID of the product variant version.
pub _id: Uuid,
/// Price of the product variant version.
pub price: u64,
/// UUID of tax rate version associated with order item.
pub tax_rate_version_id: Uuid,
}

impl PartialOrd for ProductVariantVersion {
Expand All @@ -17,15 +23,25 @@ impl PartialOrd for ProductVariantVersion {
}
}

impl From<ProductVariantVersionEventData> for ProductVariantVersion {
fn from(value: ProductVariantVersionEventData) -> Self {
Self {
_id: value.id,
price: value.price,
tax_rate_version_id: value.tax_rate_version_id,
}
}
}

impl From<ProductVariantVersion> for Bson {
fn from(value: ProductVariantVersion) -> Self {
Bson::Document(doc!("_id": value._id))
}
}

impl From<Uuid> for ProductVariantVersion {
fn from(value: Uuid) -> Self {
ProductVariantVersion { _id: value }
impl From<ProductVariantVersion> for Uuid {
fn from(value: ProductVariantVersion) -> Self {
value._id
}
}

Expand All @@ -49,35 +65,41 @@ impl From<ProductItem> for Bson {
}
}

impl From<Uuid> for ProductItem {
fn from(value: Uuid) -> Self {
ProductItem { _id: value }
impl From<ProductItem> for Uuid {
fn from(value: ProductItem) -> Self {
value._id
}
}

/// Foreign type of a tax rate version.
/// Foreign type of a coupon.
#[derive(Debug, Serialize, Deserialize, Hash, Eq, PartialEq, Copy, Clone, SimpleObject)]
#[graphql(unresolvable)]
pub struct TaxRateVersion {
/// UUID of the tax rate version.
pub struct Coupon {
/// UUID of the coupon.
pub _id: Uuid,
}

impl PartialOrd for TaxRateVersion {
impl PartialOrd for Coupon {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self._id.partial_cmp(&other._id)
}
}

impl From<TaxRateVersion> for Bson {
fn from(value: TaxRateVersion) -> Self {
impl From<Coupon> for Bson {
fn from(value: Coupon) -> Self {
Bson::Document(doc!("_id": value._id))
}
}

impl From<Uuid> for TaxRateVersion {
impl From<Coupon> for Uuid {
fn from(value: Coupon) -> Self {
value._id
}
}

impl From<Uuid> for Coupon {
fn from(value: Uuid) -> Self {
TaxRateVersion { _id: value }
Coupon { _id: value }
}
}

Expand All @@ -101,9 +123,9 @@ impl From<Discount> for Bson {
}
}

impl From<Uuid> for Discount {
fn from(value: Uuid) -> Self {
Discount { _id: value }
impl From<Discount> for Uuid {
fn from(value: Discount) -> Self {
value._id
}
}

Expand All @@ -127,6 +149,12 @@ impl From<ShipmentMethod> for Bson {
}
}

impl From<ShipmentMethod> for Uuid {
fn from(value: ShipmentMethod) -> Self {
value._id
}
}

impl From<Uuid> for ShipmentMethod {
fn from(value: Uuid) -> Self {
ShipmentMethod { _id: value }
Expand Down
119 changes: 77 additions & 42 deletions src/http_event_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use mongodb::Collection;
use serde::{Deserialize, Serialize};

use crate::{
foreign_types::{Discount, ProductItem, ProductVariantVersion, ShipmentMethod, TaxRateVersion},
foreign_types::{Coupon, ProductVariantVersion, ShipmentMethod},
user::User,
};

Expand Down Expand Up @@ -33,24 +33,35 @@ impl Default for TopicEventResponse {

/// Relevant part of Dapr event wrapped in a CloudEnvelope.
#[derive(Deserialize, Debug)]
pub struct Event {
pub struct Event<T> {
pub topic: String,
pub data: EventData,
pub data: T,
}

/// Relevant part of Dapr event.data.
/// Event data containing a Uuid.
#[derive(Deserialize, Debug)]
pub struct EventData {
pub struct UuidEventData {
pub id: Uuid,
}

/// Event data containing a ProductVariantVersion.
///
/// Differs from ProductVariantVersion in the `id` field naming.
#[derive(Deserialize, Debug)]
pub struct ProductVariantVersionEventData {
/// UUID of the product variant version.
pub id: Uuid,
/// Price of the product variant version.
pub price: u64,
/// UUID of tax rate version associated with order item.
pub tax_rate_version_id: Uuid,
}

/// Service state containing database connections.
#[derive(Clone)]
pub struct HttpEventServiceState {
pub product_variant_version_collection: Collection<ProductVariantVersion>,
pub product_item_collection: Collection<ProductItem>,
pub tax_rate_version_collection: Collection<TaxRateVersion>,
pub discount_collection: Collection<Discount>,
pub coupon_collection: Collection<Coupon>,
pub shipment_method_collection: Collection<ShipmentMethod>,
pub user_collection: Collection<User>,
}
Expand All @@ -60,63 +71,47 @@ pub async fn list_topic_subscriptions() -> Result<Json<Vec<Pubsub>>, StatusCode>
let pubsub_product_variant_version = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "catalog/product-variant-version/created".to_string(),
route: "/on-topic-event".to_string(),
};
let pubsub_product_item = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "inventory/product-item/created".to_string(),
route: "/on-topic-event".to_string(),
};
let pubsub_tax_rate_version = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "tax/tax-rate-version/created".to_string(),
route: "/on-topic-event".to_string(),
route: "/on-product-variant-version-creation-event".to_string(),
};
let pubsub_discount = Pubsub {
let pubsub_coupon = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "discount/discount/created".to_string(),
route: "/on-topic-event".to_string(),
topic: "discount/coupon/created".to_string(),
route: "/on-id-creation-event".to_string(),
};
let pubsub_shipment_method = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "shipment/shipment-method/created".to_string(),
route: "/on-topic-event".to_string(),
route: "/on-id-creation-event".to_string(),
};
let pubsub_user = Pubsub {
pubsubname: "pubsub".to_string(),
topic: "user/user/created".to_string(),
route: "/on-topic-event".to_string(),
route: "/on-id-creation-event".to_string(),
};
Ok(Json(vec![
pubsub_product_variant_version,
pubsub_product_item,
pubsub_tax_rate_version,
pubsub_discount,
pubsub_coupon,
pubsub_shipment_method,
pubsub_user,
]))
}

/// HTTP endpoint to receive events.
/// HTTP endpoint to receive UUID creation events.
///
/// Includes all creation events that consist of only UUIDs:
/// - Coupon
/// - ShipmentMethod
/// - User
#[debug_handler(state = HttpEventServiceState)]
pub async fn on_topic_event(
pub async fn on_id_creation_event(
State(state): State<HttpEventServiceState>,
Json(event): Json<Event>,
Json(event): Json<Event<UuidEventData>>,
) -> Result<Json<TopicEventResponse>, StatusCode> {
info!("{:?}", event);

match event.topic.as_str() {
"catalog/product-variant-version/created" => {
add_to_mongodb(&state.product_variant_version_collection, event.data.id).await?
}
"inventory/product-item/created" => {
add_to_mongodb(&state.product_item_collection, event.data.id).await?
}
"tax/tax-rate-version/created" => {
add_to_mongodb(&state.tax_rate_version_collection, event.data.id).await?
}
"discount/discount/created" => {
add_to_mongodb(&state.discount_collection, event.data.id).await?
"discount/coupon/created" => {
add_to_mongodb(&state.coupon_collection, event.data.id).await?
}
"shipment/shipment-method/created" => {
add_to_mongodb(&state.shipment_method_collection, event.data.id).await?
Expand All @@ -134,7 +129,47 @@ pub async fn on_topic_event(
Ok(Json(TopicEventResponse::default()))
}

/// Add a newly created object T to MongoDB.
/// HTTP endpoint to receive ProductVariantVersion creation events.
#[debug_handler(state = HttpEventServiceState)]
pub async fn on_product_variant_version_creation_event(
State(state): State<HttpEventServiceState>,
Json(event): Json<Event<ProductVariantVersionEventData>>,
) -> Result<Json<TopicEventResponse>, StatusCode> {
info!("{:?}", event);

let product_variant_version = ProductVariantVersion::from(event.data);
match event.topic.as_str() {
"catalog/product-variant-version/created" => {
add_product_variant_version_to_mongodb(
&state.product_variant_version_collection,
product_variant_version,
)
.await?
}
_ => {
// TODO: This message can be used for further Error visibility.
let _message = format!(
"Event of topic: `{}` is not a handleable by this service.",
event.topic.as_str()
);
return Err(StatusCode::INTERNAL_SERVER_ERROR);
}
}
Ok(Json(TopicEventResponse::default()))
}

/// Add a newly created ProductVariantVersion to MongoDB.
pub async fn add_product_variant_version_to_mongodb(
collection: &Collection<ProductVariantVersion>,
product_variant_version: ProductVariantVersion,
) -> Result<(), StatusCode> {
match collection.insert_one(product_variant_version, None).await {
Ok(_) => Ok(()),
Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR),
}
}

/// Add a newly created object: T to MongoDB.
pub async fn add_to_mongodb<T: Serialize + From<Uuid>>(
collection: &Collection<T>,
id: Uuid,
Expand Down
24 changes: 12 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ use query::Query;
mod mutation;
use mutation::Mutation;

use foreign_types::{Discount, ProductItem, ProductVariantVersion, ShipmentMethod, TaxRateVersion};
use foreign_types::{Coupon, ProductVariantVersion, ShipmentMethod};

mod user;
use user::User;

mod http_event_service;
use http_event_service::{list_topic_subscriptions, on_topic_event, HttpEventServiceState};
use http_event_service::{
list_topic_subscriptions, on_id_creation_event, on_product_variant_version_creation_event,
HttpEventServiceState,
};

mod authentication;
use authentication::AuthorizedUserHeader;
Expand Down Expand Up @@ -80,25 +83,22 @@ async fn db_connection() -> Client {
async fn build_dapr_router(db_client: Database) -> Router {
let product_variant_version_collection: mongodb::Collection<ProductVariantVersion> =
db_client.collection::<ProductVariantVersion>("product_variant_versions");
let product_item_collection: mongodb::Collection<ProductItem> =
db_client.collection::<ProductItem>("product_items");
let tax_rate_version_collection: mongodb::Collection<TaxRateVersion> =
db_client.collection::<TaxRateVersion>("tax_rate_versions");
let discount_collection: mongodb::Collection<Discount> =
db_client.collection::<Discount>("discounts");
let coupon_collection: mongodb::Collection<Coupon> = db_client.collection::<Coupon>("coupons");
let shipment_method_collection: mongodb::Collection<ShipmentMethod> =
db_client.collection::<ShipmentMethod>("shipment_methods");
let user_collection: mongodb::Collection<User> = db_client.collection::<User>("users");

// Define routes.
let app = Router::new()
.route("/dapr/subscribe", get(list_topic_subscriptions))
.route("/on-topic-event", post(on_topic_event))
.route("/on-id-creation-event", post(on_id_creation_event))
.route(
"/on-product-variant-version-creation-event",
post(on_product_variant_version_creation_event),
)
.with_state(HttpEventServiceState {
product_variant_version_collection,
product_item_collection,
tax_rate_version_collection,
discount_collection,
coupon_collection,
shipment_method_collection,
user_collection,
});
Expand Down
Loading

0 comments on commit 39b3ef7

Please sign in to comment.