24 C
en
  • Home
  • Blog
  • About
MyCovers, covering dynamic ecommerce

Mega Menu

  • NEWS
  • REVIEWS
  • RECOMMENDED PRODUCTS
  • EDUCATIONAL ARTICLES
    • Hydrogen
    • React
    • Tailwind
    • UI/UX
    • Design
  • YOUTUBE
MyCovers, covering dynamic ecommerce
Search
Home Backend Headless eCommerce HotNews Hydrogen TechNews Shopify Hydrogen App Development Tutorial 101 Part 2 - Partner App Backend Integration using Temporal.io (Demo App Porting - ep 1)
Backend Headless eCommerce HotNews Hydrogen TechNews

Shopify Hydrogen App Development Tutorial 101 Part 2 - Partner App Backend Integration using Temporal.io (Demo App Porting - ep 1)

Faiza Tanjia
Faiza Tanjia
10 May, 2022 0 0
Facebook
Twitter
Telegram
WhatsApp
Partner App Backend Integration using Temporal.io (Demo App Porting - ep 1)

1. Introduction

In this episode 1 blog post, we will create a demo eCommerce app using Temporal.io with Javascript. This post is the porting version from the original written in GoLang, you can check out the original post at https://docs.temporal.io/blog/build-an-ecommerce-app-with-temporal-part-1/

We will add a new feature for creating an e-money billing after the user checked out their cart that we’ll be visiting for the next part of this post. The e-money feature will only be included for testing since in the last part we will integrate this partner backend with hydrogen (hydrogen uses its own payment method (Shopify Payment)).

2. Getting Started

2.1. Download Temporalite

To run temporal locally (what we’ll be doing to run our app), we need to download the package. I will be using the temporalite version of the server because of the easy setup and no dependencies on a container runtime needed.

Build from source using go install:

Note: Go 1.17 or greater is currently required.

go install github.com/DataDog/temporalite/cmd/temporalite@latest

2.2. Create a New Project and Start Temporal Locally

2.2.1. Create a new project

Use the package initializer to create a new project. We will named it temporal-ecommerce.

npx @temporalio/create@latest ./temporal-ecommerce cd example

This will create a project with a starter sample, when asked for which sample that would you like to use, choose the hello-world-js starter

Which-sample-would-you-like-to-use

2.2.2. Start temporal server

temporalite start -f my_test.db --namespace default --ip 0.0.0.0

At this point you should have a server running on localhost:7233 and a web interface at http://localhost:8233.

2.3. Installing Dependencies

Below are the dependencies we’ll need to install before moving on:
  1. body-parser (v1.20.0)
  2. express (v4.18.1)
  3. midtrans-client (v1.3.1)
  4. node-mailjet (v3.3.13)
  5. temporal-rest (v0.4.0)
  6. uuid (v8.3.2)
Install in your project directory

npm i body-barser express midtrans-client node-mailjet temporal-rest uuid

2.4. Temporal Components

Below are temporal components that we will be seeing upon starter installation.

1. Activity

Activities are called from Workflows in order to run non-deterministic code

Any async function can be used as an Activity as long as its parameters and return value are serializable. Activities run in the Node.js execution environment, meaning you can easily port over any existing code into an Activity and it should work.

src/activities.js

2. Workflow

A Workflow is also an async function, but it has access to special Workflow APIs like Signals, Queries, Timers, and Child Workflows.

src/workflows.js

3. Worker

The Worker hosts Workflows and Activities, connects to Temporal Server, and continually polls a Task Queue for Commands coming from Clients

src/worker.js

4. Client

The WorkflowClient class is used to interact with existing Workflows or to start new ones./p>

It can be used in any Node.js process (for example, an Express web server) and is separate from the Worker.

src/client.js

3. Shopping Cart Workflow

Like what is explained in temporal.io docs I mentioned above, the ecommerce shopping cart app built is unlike the usual traditional architecture. Most common practice is to save the user cart activities in a database, but with temporal, you can represent a shopping cart as a long-living workflow.

For now, the shopping cart workflow would look like the following (as we haven’t added any functionalities)

src/workflows.js

import { proxyActivities } from '@temporalio/workflow'; const { greet } = proxyActivities({ startToCloseTimeout: '1 minute', }); /** Cart workflow */ export async function CartWorkflow() { console.log(‘Hello temporal!); }

To run a Workflow, you need to create a Worker process. A Temporal Worker listens for events on a queue and has a list of registered Workflows that it can run in response to messages on the queue. Hello-world-js starter already included the worker file. We won’t need to write or change the file ourselves (we still need to change the TaskQueue value, though).

Below is the worker.

src/worker.js

/** Worker hosts workflows and activities, connects to temporal server, * continually polls a task queue for commands */ import { Worker } from '@temporalio/worker'; import { URL } from 'url'; import * as activities from './activities.js'; async function run() { // step 1: register Workflows and Activities // and connect to the Temporal server const worker = await Worker.create({ workflowsPath: new URL('./workflows.js', import.meta.url).pathname, activities, taskQueue: 'temporal-ecommerce' }); // Step 2: Start accepting tasks on the 'tutorial' queue await worker.run() } run().catch((err) => { console.error(err); process.exit(1) })

4. Adding and removing product

When we’re talking about shopping cart, the main functionality of a cart is to allow users to put some things or remove some from the cart, In order to do that, workflow signals are needed (for both adding and removing items). Workflow then will listen to events triggering these signals and executing it. The code below is to define both add to cart and remove from cart signals.

src/workflows.js

import * as wf from '@temporalio/workflow'; const { greet } = wf.proxyActivities({ startToCloseTimeout: '1 minute', }); /** Add To Cart Signal */ export const AddToCartSignal = wf.defineSignal('AddToCart'); /** Remove Product from Cart Signal*/ export const RemoveFromCartSignal = wf.defineSignal('RemoveFromCart'); /** Cart workflow */ export async function CartWorkflow() { console.log(‘Hello temporal!); }

The signals need to have handlers, so when these signals are called, it will execute the handler function. Both the signals are used to modify the cart state (where the user places their items). Since we haven’t created the cart state and signal handlers, the following is the code to do that.

Creating useState utility

src/workflows.js

// .... /** Cart workflow */ export async function CartWorkflow() { // .... } /** Utility state function */ function useState(name, initialValue) { const signal = wf.defineSignal(name); const query = wf.defineQuery(name); let state = initialValue; wf.setHandler(signal, (newValue) => { console.log('Updating...', name, newValue); state = newValue; }); wf.setHandler(query, () => state); return { signal, query, get value() { // need to use closure because function doesn't rerun unlike React hooks return state; }, set value(newVal) { state = newVal; } } }

Creating cart state

src/workflows.js

// .... /** Cart workflow */ export async function CartWorkflow() { // create CartState const CartState = useState("CartState", {items: [], status: 'IN_PROGRESS', email: '', name: ''}); }

Now the handler for AddToCartSignal

src/workflows.js

// .... /** Cart workflow */ export async function CartWorkflow() { // create CartState const CartState = useState("CartState", {items: [], status: 'IN_PROGRESS', email: '', name: ''}); /** Add to Cart Handler */ wf.setHandler(AddToCartSignal, function addToCartSignal(product) { // find existing item const existingItem = CartState.value.items.find(({ productId }) => productId === product.productId); // if it already exists, add the quantity by product.quantity if (existingItem !== undefined) { existingItem.quantity += product.quantity; } else { CartState.value.items.push(product); // Instead if it doesn't exist, push the product to cart array } console.log('Add To Cart Handler done.') }); }

If this certain product the user added have never existed on the cart, the workflow will add all the product attributes to the cart. If the product already exists, it will simply add the number of quantity by the number of product quantity added to the cart.

RemoveFromCart signal handler

src/workflows.js

// .... /** Cart workflow */ export async function CartWorkflow() { // create CartState const CartState = useState("CartState", {items: [], status: 'IN_PROGRESS', email: '', name: ''}); /** Add to Cart Handler */ // .... /** Remove From Cart Handler*/ wf.setHandler(RemoveFromCartSignal, function removeFromCartSignal(product) { // find product index const index = CartState.value.items.findIndex(({ productId }) => productId === product.productId); // if product not found, return if (index === -1) { console.log('No product found: ', product); return; } // if it doesn't pass the if check, it means the product is available. Find the existing item const existingItem = CartState.value.items[index]; // remove the quantity of the product existingItem.quantity -= product.quantity; // if the quantity is reduced to 0, remove product from cart completely if (existingItem.quantity <= 0) { CartState.value.items.splice(index, 1); // at position index, remove that product in that position }; console.log('Remove product handler done.'); }); }

Before removing the product, the handler will check whether the selected product already exists on the cart. After it passes the check, it will remove the quantity, and whenever the quantity drops to zero, the product will be deleted from the cart.

5. Next up

Although it doesn’t make things significantly simpler when writing this simple CRUD application like this. For the next post, we can see a case where temporal really shines (sending a cart abandonment email when it passes a timeout and ending the workflow when the transaction is settled) !

Via Backend
Facebook
Twitter
Telegram
WhatsApp
Older Posts
Newer Posts

You may like these posts

Post a Comment

Ads Single Post 4

Faiza Tanjia

About Us

Hi, I am Faiza, one of the team leaders here at MyCovers. We are passionate about Dynamic eCommerce and love sharing our knowledge and research with you. At MyCovers, we strive to be the ultimate resource for learning everything Covering Dynamic eCommerce Application Development!

Featured Post

Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

Faiza Tanjia- May 11, 2022
Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

May 11, 2022
Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

May 10, 2022
Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

February 07, 2022
Headless eCommerce: from a Complementary to Elementary Disruptive Business Strategy

Headless eCommerce: from a Complementary to Elementary Disruptive Business Strategy

February 17, 2022

Editor Post

Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

February 07, 2022
Headless eCommerce: from a Complementary to Elementary Disruptive Business Strategy

Headless eCommerce: from a Complementary to Elementary Disruptive Business Strategy

February 17, 2022
Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

May 10, 2022

Popular Post

Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

Shopify Hydrogen App Development Tutorial 101 Part 4 - Partner App Backend Integration using Temporal.io (Partner Backend API - ep 3)

May 11, 2022
Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

Shopify Hydrogen App Development Tutorial 101 Part 3 - Partner App Backend Integration using Temporal.io (Shopping Cart and Payment - ep 2)

May 10, 2022
Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

Shopify App Development using React based Hydrogen Framework: A Comprehensive Tutorial 101 (part 1)

February 07, 2022

Popular Categories

  • Backend 3
  • Business Strategy 1
  • Headless eCommerce 5
  • Hydrogen 4
  • React 1
  • Tailwind 1
MyCovers, covering dynamic ecommerce

MyCovers

Your ultimate resources for learning everything about Dynamic eCommerce Application Development

Follow Us

Copyright © 2022 MyCovers

  • About
  • Contact Us
  • Accessibility
  • Privacy Policy
  • Disclaimer