Nedir Bu Temporal.IO?

  • Tanımak: Temporal.io Nedir?, Nasıl Çalışır?
  • Anlamak: Hangi şirketler kullanıyor?, Ne zaman kullandım?
  • Öğrenmek: Golang ile basit bir workflow geliştirelim.
https://www.temporal.io

A) Tanımak

Interior design of Temporal Service
  • Macthing Service: Gönderme için Görev Kuyruklarını barındırır
  • Worker Service: Dahili arka plan iş akışları için çalışır
  • History Service: Verileri tutar (değişebilir durum, kuyruklar ve zamanlayıcılar)
  • Frontend Service: Hız sınırlama, yönlendirme, yetkilendirme için çalışır
Temporal Web UI
Temporal CLI

B) Anlamak

C) Öğrenmek

  • activity : Tüm aktiviteler orada tutulur.
  • client: İstemci, iş akışını başlatıcı veya işaretçi olarak tetikleyen bir Dinlenme API’sidir.
  • engine: temporal-service’i çalıştırmak için bir docker-compose.yml dosyasına sahiptir
  • signals: Tüm sinyalleri oraya yazmalıyız, örneğin ödeme sinyali
  • starters: starter’lar workflowları başlatır. bu arada önceki ekibimdeki tüm iş akışları için dinamik bir iş akışı başlatıcı kullanmıştık.
  • worker: Bunu biliyoruz, tüm faaliyetleri temporal-service‘in verdiği talimatlar ile yürütür.
  • workflows: bunlar bizim iş akışı şemalarımızdır. tüm adımları onlarda ayarlayabiliriz.
package activities

import (
"context"
"log"
)

func PrepareCoffee(ctx context.Context) error {
log.Println("Coffee is preparing...")
return nil
}

func GiveCoffee(ctx context.Context, customerName string) error {
log.Printf("%s adlı müşteriye kahve teslim edildi.", customerName)
return nil
}

func WriteAsDept(ctx context.Context, customerName string) error {
log.Printf("%s borrowed a coffee", customerName)
return nil
}
package signals

import (
"context"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/workflow"
"log"
)

const (
PAYMENT_SIGNAL = "payment_signal"
)

func SendPaymentSignal(workflowID string, paymentStatus bool) (err error) {
temporalClient, err := client.NewClient(client.Options{})
if err != nil {
log.Fatalln("Unable to create Temporal client", err)
return
}

err = temporalClient.SignalWorkflow(context.Background(), workflowID, "", PAYMENT_SIGNAL, paymentStatus)
if err != nil {
log.Fatalln("Error signaling client", err)
return
}

return nil
}

func ReciveSignal(ctx workflow.Context, signalName string) (paymentStatus bool){
workflow.GetSignalChannel(ctx, signalName).Receive(ctx, &paymentStatus)
return
}
package workflowsimport (
"github.com/alameddinc/temporal-workflow-golang-example/activities"
"github.com/alameddinc/temporal-workflow-golang-example/signals"
"go.temporal.io/sdk/workflow"
"log"
"time"
)
func CoffeeShopWorkflow(ctx workflow.Context, customerName string) error {
// We set our activity options with ActivtiyOptions
// if we want to use childworkflow and if we want to set custom settings for that
// we should use ChildWorkflowOptions like that.
ao := workflow.ActivityOptions{
StartToCloseTimeout: 50 * time.Second,
ScheduleToCloseTimeout: 100 * time.Second,
}
ctx = workflow.WithActivityOptions(ctx, ao)
// the workflow is preparing coffee with PrepareCoffee activity
workflow.ExecuteActivity(ctx, activities.PrepareCoffee, nil).Get(ctx, nil)
workflow.Sleep(ctx, 5 * time.Second)
log.Println("Coffee is ready to serve")
// Customer paid bill
if status := signals.ReciveSignal(ctx, signals.PAYMENT_SIGNAL); !status{
log.Println("Payment couldn't be completed! ")
// We sent customerName to WriteAsDept activity for It can write an dept to him
workflow.ExecuteActivity(ctx, activities.WriteAsDept, customerName).Get(ctx, nil)
}
// Customer took coffee
workflow.ExecuteActivity(ctx, activities.GiveCoffee, customerName).Get(ctx, nil)
return nil
}
package main

package main

import (
"github.com/alameddinc/temporal-workflow-golang-example/activities"
"github.com/alameddinc/temporal-workflow-golang-example/workflows"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
"log"
)

func main() {
log.Println("Worker Starting...")
opt := client.Options{
HostPort:client.DefaultHostPort,
}
c, err := client.NewClient(opt)
if err != nil {
log.Fatalln("unable to create Temporal client", err)
}
defer c.Close()
w := worker.New(c, "worker-group-1", worker.Options{})
w.RegisterWorkflow(workflows.CoffeeShopWorkflow)
w.RegisterActivity(activities.PrepareCoffee)
w.RegisterActivity(activities.WriteAsDept)
w.RegisterActivity(activities.GiveCoffee)
if err := w.Run(worker.InterruptCh()); err != nil{
log.Fatalln(err)
}

}
package starters

import (
"context"
"github.com/alameddinc/temporal-workflow-golang-example/workflows"
"go.temporal.io/sdk/client"
)

func StartWorkflowFunc(workflowID string, customerName string){
c, err := client.NewClient(client.Options{})
if err != nil {
panic(err)
}
defer c.Close()
opt := client.StartWorkflowOptions{
ID: workflowID,
TaskQueue: "worker-group-1",
}
ctx := context.Background()
if _, err := c.ExecuteWorkflow(ctx, opt, workflows.CoffeeShopWorkflow, customerName); err != nil{
panic(err)
}
}
package main

import (
"github.com/alameddinc/temporal-workflow-golang-example/signals"
"github.com/alameddinc/temporal-workflow-golang-example/starters"
"github.com/google/uuid"
"github.com/gorilla/mux"
"log"
"net/http"
)

func main() {
r := mux.NewRouter()
r.HandleFunc("/about", GetAbout)
r.HandleFunc("/start-workflow", StartWorkflow)
r.HandleFunc("/send-signal/{workflowID}", SendSignal)
log.Fatal(http.ListenAndServe(":3310", r))
}

func SendSignal(writer http.ResponseWriter, request *http.Request) {
vars := mux.Vars(request)
workflowId := vars["workflowID"]
if err := signals.SendPaymentSignal(workflowId, true); err != nil {
writer.Write([]byte(err.Error()))
return
}
writer.Write([]byte("Sent it"))
return
}

func StartWorkflow(writer http.ResponseWriter, request *http.Request) {
workflowUUID, err := uuid.NewUUID()
if err != nil {
writer.Write([]byte(err.Error()))
return
}
starters.StartWorkflowFunc(workflowUUID.String(), "alameddin")
writer.Write([]byte("OK"))
}

func GetAbout(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("It's running..."))
}
Worker Started
Client Started
by the way If you think why we used 3310 to port number, Its for respect to Nokia :)

--

--

--

Bilgisayar Mühendisi

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alameddin Çelik

Alameddin Çelik

Bilgisayar Mühendisi

More from Medium

An adventure with the asynchronous multi-threaded time-series data processing in Python over…

State of Golang linters and the differences between them — SourceLevel

Learn gRPC : 5 minute read

Sample Go daemon process using context, wait and signal (Ctrl-C)