{"id":3707,"date":"2021-02-21T21:47:39","date_gmt":"2021-02-21T20:47:39","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=3707"},"modified":"2021-02-22T17:04:53","modified_gmt":"2021-02-22T16:04:53","slug":"implementation-of-choreography-based-saga-in-dotnet-microservices","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/implementation-of-choreography-based-saga-in-dotnet-microservices\/","title":{"rendered":".NET Microservice&#8217;lerinde Choreography-based Saga"},"content":{"rendered":"<p>G\u00fcn\u00fcm\u00fcz teknoloji \u00e7a\u011f\u0131nda neredeyse hepimiz microservice&#8217;ler hakk\u0131nda konu\u015fuyor ve uygulamalar geli\u015ftirmeye \u00e7al\u0131\u015f\u0131yoruz. Y\u00fczeysel bakt\u0131\u011f\u0131m\u0131zda her \u015fey \u00e7ok net ve uygulamas\u0131 kolay gibi g\u00f6r\u00fcnsede, \u00f6zellikle s\u00f6z konusu distributed transaction y\u00f6netimi oldu\u011funda i\u015fler daha karma\u015f\u0131k bir hal almaya ba\u015fl\u0131yor.<\/p>\n<p>\u00c7\u00fcnk\u00fc business&#8217;\u0131m\u0131z\u0131n sa\u011fl\u0131kl\u0131 bir \u015fekilde ilerleyebilmesini sa\u011flayabilmemiz ve nihai business outcome&#8217;\u0131na ula\u015fabilmemiz i\u00e7in, data&#8217;n\u0131n tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flayabilmemiz gerekmektedir.<\/p>\n<p>Bu makale kapsam\u0131nda ise distributed ortamlarda transaction i\u015flemlerini, <strong>Choreography-based<\/strong> <strong>Saga<\/strong> pattern&#8217;\u0131 ile nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimizi g\u00f6stermeye \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<h2>Choreography-based Saga<\/h2>\n<p>Distributed ortamlardaki transaction y\u00f6netimi konusunda saga pattern&#8217;\u0131 bizlere &#8220;<em>Choreography<\/em>&#8221; ve &#8220;<em>Orchestration<\/em>&#8221; olmak \u00fczere iki farkl\u0131 yakla\u015f\u0131m sunmaktad\u0131r.<\/p>\n<p>2017 y\u0131l\u0131nda saga pattern&#8217;\u0131n\u0131 orchestration yakla\u015f\u0131m\u0131 ile nas\u0131l implemente edebilece\u011fimizi <em><a href=\"https:\/\/gokhan-gokalp.com\/masstransit-saga-state-machine-ile-model-workflow-u-olusturmak\/\" target=\"_blank\" rel=\"noopener\">buradaki<\/a><\/em> makalemde ele almaya \u00e7al\u0131\u015fm\u0131\u015ft\u0131m. Bu makale kapsam\u0131nda ise herhangi bir orchestrator&#8217;a sahip olmadan saga pattern&#8217;\u0131n\u0131 loosely coupled olarak nas\u0131l implemente edebilece\u011fimizi g\u00f6stermeye \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<figure id=\"attachment_3710\" aria-describedby=\"caption-attachment-3710\" style=\"width: 852px\" class=\"wp-caption aligncenter\"><a href=\"\/wp-content\/uploads\/2021\/01\/choreography-saga.jpg\"><img decoding=\"async\" class=\"wp-image-3710 size-full lazyload\" data-src=\"\/wp-content\/uploads\/2021\/01\/choreography-saga.jpg\" alt=\"\" width=\"852\" height=\"480\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/choreography-saga.jpg 852w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/choreography-saga-300x169.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/choreography-saga-768x433.jpg 768w\" data-sizes=\"(max-width: 852px) 100vw, 852px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 852px; --smush-placeholder-aspect-ratio: 852\/480;\" \/><\/a><figcaption id=\"caption-attachment-3710\" class=\"wp-caption-text\">https:\/\/cirendanceclub.org.uk\/wp-content\/uploads\/2018\/09\/12.jpg<\/figcaption><\/figure>\n<p>Choreography-based saga yakla\u015f\u0131m\u0131ndaki ana fikir, her microservice&#8217;in bireysel olarak sorumluluklar\u0131n\u0131 s\u0131ras\u0131yla yerine getirmesine ve consistency&#8217;i sa\u011flayabilmek i\u00e7in beraber hareket etmelerine dayanmaktad\u0131r.<\/p>\n<p>Bir ba\u015fka de\u011fi\u015fle her microservice kendi sorumlulu\u011funu yerine getirdi\u011finde, transaction&#8217;\u0131 distributed ve asynchronous olarak devam ettirebilmesi i\u00e7in bir sonraki a\u015famay\u0131 ilgili bir business event&#8217;i ile tetiklemesi gerekmektedir.<\/p>\n<h2>Senaryo<\/h2>\n<p>Bir e-ticaret firmas\u0131nda \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131z\u0131 ve \u00f6demeleri asynchronous olarak ger\u00e7ekle\u015ftirebilmek i\u00e7in a\u015fa\u011f\u0131daki gibi basit bir flow&#8217;a sahip oldu\u011fumuzu d\u00fc\u015f\u00fcnelim.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2021\/01\/saga-happy-path.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-3714 lazyload\" data-src=\"\/wp-content\/uploads\/2021\/01\/saga-happy-path.jpg\" alt=\"\" width=\"822\" height=\"322\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/saga-happy-path.jpg 822w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/saga-happy-path-300x118.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/01\/saga-happy-path-768x301.jpg 768w\" data-sizes=\"(max-width: 822px) 100vw, 822px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 822px; --smush-placeholder-aspect-ratio: 822\/322;\" \/><\/a><\/p>\n<p>Yukar\u0131daki happy-path flow&#8217;a bakt\u0131\u011f\u0131m\u0131zda;<\/p>\n<ol>\n<li>Client sipari\u015f i\u015flemini &#8220;<em>Order Service<\/em>&#8221; arac\u0131l\u0131\u011f\u0131 ile ger\u00e7ekle\u015ftirir ve bu service &#8220;Pending&#8221; durumunda bir sipari\u015f yarat\u0131r. Ard\u0131ndan &#8220;OrderCreatedEvent&#8221; ini publish eder.<\/li>\n<li>Stock i\u015flemlerinden sorumlu &#8220;<em>Stock Service<\/em>&#8221; i &#8220;OrderCreatedEvent&#8221; ini dinler ve ilgili \u00fcr\u00fcnlerin stock&#8217;lar\u0131n\u0131 reserve eder. Ard\u0131ndan &#8220;StockReservedEvent&#8221; ini publish eder.<\/li>\n<li>Payment i\u015flemlerinden sorumlu &#8220;<em>Payment Service<\/em>&#8221; i &#8220;StockReservedEvent&#8221; ini dinler ve ilgili \u00f6deme i\u015flemlerini ger\u00e7ekle\u015ftirmeye \u00e7al\u0131\u015f\u0131r. \u00d6deme i\u015flemi ba\u015far\u0131yla ger\u00e7ekle\u015ftirilirse, &#8220;PaymentCompletedEvent&#8221; ini publish eder.<\/li>\n<li>&#8220;<em>Order Service<\/em>&#8221; i transaction&#8217;\u0131 sonland\u0131rabilmek i\u00e7in ise &#8220;PaymentCompletedEvent&#8221; ini dinler ve ilgili order&#8217;\u0131n durumunu &#8220;Pending&#8221; den &#8220;Completed&#8221; a \u00e7eker. B\u00f6ylece i\u015flem, distributed ve consistent bir \u015fekilde microservice&#8217;ler aras\u0131nda tamamlanm\u0131\u015f olur.<\/li>\n<\/ol>\n<h2>Implemente Edelim<\/h2>\n<p>Implementasyon k\u0131sm\u0131n\u0131 a\u00e7\u0131klamaya ge\u00e7meden \u00f6nce, \u00f6rnek projenin tamam\u0131na <em><a href=\"https:\/\/github.com\/GokGokalp\/choreography-saga-dotnet\" target=\"_blank\" rel=\"noopener\">buradan<\/a><\/em> ula\u015fabilirsiniz.<\/p>\n<p>Yukar\u0131daki happy-path flow&#8217;a ek olarak a\u015fa\u011f\u0131daki gibi business requirement&#8217;lar\u0131na da sahip oldu\u011fumuzu varsayal\u0131m:<\/p>\n<ul>\n<li>Asynchronous olarak ger\u00e7ekle\u015ftirilecek \u00f6deme i\u015flemi s\u0131ras\u0131nda herhangi bir hata meydana gelirse, &#8220;<em>PaymentRejectedEvent<\/em>&#8221; ad\u0131nda bir event publish edilecek.<\/li>\n<li>&#8220;<em>PaymentRejectedEvent<\/em>&#8221; event&#8217;i Stock Service&#8217;i taraf\u0131ndan consume edilecek ve stok&#8217;lar\u0131 reserve edilen \u00fcr\u00fcnler tekrardan release edilebilecek. Ard\u0131ndan &#8220;<em>StocksReleasedEvent<\/em>&#8221; ad\u0131nda bir event publish edilecek.<\/li>\n<li>&#8220;<em>StocksReleasedEvent<\/em>&#8221; event&#8217;i ise Order Service&#8217;i taraf\u0131ndan consume edilecek ve ilgili sipari\u015f&#8217;in durumu <strong>pending<\/strong> durumundan <strong>rejected<\/strong> durumuna \u00e7ekilecek.<\/li>\n<\/ul>\n<h3>Order API<\/h3>\n<p>Sistem i\u00e7erinde bir sipari\u015f olu\u015fturabilmek i\u00e7in Order API a\u015fa\u011f\u0131daki gibi bir controller ve service&#8217;e sahiptir.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">[ApiController]\r\n[Route(\"[controller]\")]\r\npublic class OrdersController : ControllerBase\r\n{\r\n    private readonly IOrderService _orderService;\r\n\r\n    public OrdersController(IOrderService orderService)\r\n    {\r\n        _orderService = orderService;\r\n    }\r\n\r\n    [HttpPost]\r\n    public async Task&lt;IActionResult&gt; CreateOrder(CreateOrderRequest request)\r\n    {\r\n        await _orderService.CreateOrderAsync(request);\r\n\r\n        return Accepted();\r\n    }\r\n}<\/pre>\n<\/div>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class OrderService : IOrderService\r\n{\r\n    private readonly IBus _bus;\r\n\r\n    public OrderService(IBus bus)\r\n    {\r\n        _bus = bus;\r\n    }\r\n\r\n    public async Task CreateOrderAsync(CreateOrderRequest request)\r\n    {\r\n        \/\/ Order creation logic in \"Pending\" state.\r\n\r\n        await _bus.PubSub.PublishAsync(new OrderCreatedEvent\r\n        {\r\n            UserId = 1,\r\n            OrderId = 1,\r\n            WalletId = 1,\r\n            TotalAmount = request.TotalAmount,\r\n        });\r\n    }\r\n\r\n    public Task CompleteOrderAsync(int orderId)\r\n    {\r\n        \/\/ Change the order status as completed.\r\n\r\n        return Task.CompletedTask;\r\n    }\r\n\r\n    public Task RejectOrderAsync(int orderId, string reason)\r\n    {\r\n        \/\/ Change the order status as rejected.\r\n\r\n        return Task.CompletedTask;\r\n    }\r\n}<\/pre>\n<\/div>\n<p>&#8220;<em>CreateOrderAsync<\/em>&#8221; method&#8217;u, sipari\u015f&#8217;i ilk olarak <strong>pending<\/strong> durumunda olu\u015fturdu\u011fumuz noktad\u0131r. \u00c7\u00fcnk\u00fc bu a\u015famada hen\u00fcz sipari\u015f i\u00e7erisindeki \u00fcr\u00fcnlerin stok durumlar\u0131n\u0131 veya \u00f6demeyi ba\u015far\u0131yla ger\u00e7ekle\u015ftirip ger\u00e7ekle\u015ftiremeyece\u011fimizi bilmiyoruz.<\/p>\n<p>Sipari\u015f olu\u015fturulduktan sonra ise distributed bir \u015fekilde i\u015flem b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc sa\u011flayabilmemiz i\u00e7in, &#8220;<em>OrderCreatedEvent<\/em>&#8221; ad\u0131nda bir event publish ediyoruz. Bir nevi i\u015flemler zincirin bir sonraki a\u015famas\u0131n\u0131 burada tetikliyoruz.<\/p>\n<p>&#8220;<em>CompleteOrderAsync<\/em>&#8221; method&#8217;unu ise, t\u00fcm i\u015flemlerin ba\u015far\u0131yla ger\u00e7ekle\u015fti\u011fi durumda sipari\u015fi <strong>pending<\/strong> durumundan <strong>completed<\/strong> durumuna g\u00fcncelleyebilmek i\u00e7in kullanaca\u011f\u0131z.<\/p>\n<p>\u0130\u015flemlerin ba\u015far\u0131yla tamamlan\u0131p tamamlanmad\u0131\u011f\u0131n\u0131 Order Service&#8217;in anlayabilmesi i\u00e7in ise, i\u00e7erisinde i\u015flemler zincirinin son par\u00e7as\u0131 olan &#8220;<em>PaymentCompletedEvent<\/em>&#8221; ini dinleyen a\u015fa\u011f\u0131daki gibi bir consumer bulunmaktad\u0131r.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class PaymentCompletedEventConsumer : IConsumeAsync&lt;PaymentCompletedEvent&gt;\r\n{\r\n    private readonly IOrderService _orderService;\r\n\r\n    public PaymentCompletedEventConsumer(IOrderService orderService)\r\n    {\r\n        _orderService = orderService;\r\n    }\r\n\r\n    public async Task ConsumeAsync(PaymentCompletedEvent message, CancellationToken cancellationToken = default)\r\n    {\r\n        await _orderService.CompleteOrderAsync(message.OrderId);\r\n    }\r\n}<\/pre>\n<\/div>\n<p>Ayr\u0131ca\u00a0&#8220;<em>RejectOrderAsync<\/em>&#8221; method&#8217;unu da, \u00f6deme i\u015flemleri a\u015famas\u0131nda olu\u015fabilecek herhangi bir hata durumunda ilgili sipari\u015fi <strong>rejected<\/strong> durumuna getirebilmek i\u00e7in kullanaca\u011f\u0131z.<\/p>\n<p>Order Service&#8217;in ilgili sipari\u015f durumunu <strong>rejected<\/strong> olarak g\u00fcncelleyebilmesi i\u00e7in ise, Stock Service&#8217;inin ilgili \u00fcr\u00fcn stok&#8217;lar\u0131n\u0131 tekrardan release ettikten sonra publish etti\u011fi &#8220;<em>StocksReleasedEvent<\/em>&#8221; ini a\u015fa\u011f\u0131daki gibi consume etmektedir.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class StocksReleasedEventConsumer : IConsumeAsync&lt;StocksReleasedEvent&gt;\r\n{\r\n    private readonly IOrderService _orderService;\r\n\r\n    public StocksReleasedEventConsumer(IOrderService orderService)\r\n    {\r\n        _orderService = orderService;\r\n    }\r\n\r\n    public async Task ConsumeAsync(StocksReleasedEvent message, CancellationToken cancellationToken = default)\r\n    {\r\n        await _orderService.RejectOrderAsync(message.OrderId, message.Reason);\r\n    }\r\n}<\/pre>\n<\/div>\n<h3><\/h3>\n<h3>Stock Service<\/h3>\n<p>Sistem i\u00e7erisinde bir sipari\u015f <strong>pending<\/strong> durumunda olu\u015fturuldu\u011funda, o sipari\u015f i\u00e7erisindeki \u00fcr\u00fcnlerin stok&#8217;lar\u0131 Stock Service&#8217;i taraf\u0131ndan rezerve edilmektedir.<\/p>\n<p>Bunun i\u00e7in Stock Service&#8217;i i\u00e7erisinde &#8220;<em>OrderCreatedEvent<\/em>&#8221; ini dinleyen a\u015fa\u011f\u0131daki gibi bir consumer bulunmaktad\u0131r.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class OrderCreatedEventConsumer : IConsumeAsync&lt;OrderCreatedEvent&gt;\r\n{\r\n    private readonly IStockService _stockService;\r\n    private readonly IBus _bus;\r\n\r\n    public OrderCreatedEventConsumer(IStockService stockService, IBus bus)\r\n    {\r\n        _stockService = stockService;\r\n        _bus = bus;\r\n    }\r\n\r\n    public async Task ConsumeAsync(OrderCreatedEvent message, CancellationToken cancellationToken = default)\r\n    {\r\n        await _stockService.ReserveStocksAsync(message.OrderId);\r\n\r\n        await _bus.PubSub.PublishAsync(new StocksReservedEvent\r\n        {\r\n            UserId = message.UserId,\r\n            OrderId = message.OrderId,\r\n            WalletId = message.WalletId,\r\n            TotalAmount = message.TotalAmount\r\n        });\r\n    }\r\n}<\/pre>\n<\/div>\n<p>Bu consumer i\u00e7erisinde basit olarak \u00fcr\u00fcnlerin stok&#8217;lar\u0131n\u0131n rezerve i\u015flemleri ger\u00e7ekle\u015ftirilip, ard\u0131ndan &#8220;<em>StockReservedEvent<\/em>&#8221; i publish edilmektedir. B\u00f6ylelikle sipari\u015f i\u015flem b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fcn bir a\u015famas\u0131 daha tamamlan\u0131p, bir sonraki a\u015famas\u0131 tetiklenmi\u015f olmaktad\u0131r.<\/p>\n<p>Ayr\u0131ca \u00f6deme i\u015flemlerinde olu\u015fabilecek herhangi bir hata durumuna ka\u015f\u0131 rezerve edilen \u00fcr\u00fcnlerin stok&#8217;lar\u0131n\u0131n tekrardan release edilebilmesi i\u00e7in, &#8220;<em>PaymentRejectedEvent<\/em>&#8221; ini dinleyen a\u015fa\u011f\u0131daki gibi bir consumer&#8217;a da sahiptir.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class PaymentRejectedEventConsumer : IConsumeAsync&lt;PaymentRejectedEvent&gt;\r\n{\r\n    private readonly IStockService _stockService;\r\n    private readonly IBus _bus;\r\n\r\n    public PaymentRejectedEventConsumer(IStockService stockService, IBus bus)\r\n    {\r\n        _stockService = stockService;\r\n        _bus = bus;\r\n    }\r\n\r\n    public async Task ConsumeAsync(PaymentRejectedEvent message, CancellationToken cancellationToken = default)\r\n    {\r\n        await _stockService.ReleaseStocksAsync(message.OrderId);\r\n\r\n        await _bus.PubSub.PublishAsync(new StocksReleasedEvent\r\n        {\r\n            OrderId = message.OrderId,\r\n            Reason = message.Reason\r\n        });\r\n    }\r\n}<\/pre>\n<\/div>\n<h3><\/h3>\n<h3>Payment Service<\/h3>\n<p>Sipari\u015f i\u00e7erisindeki \u00fcr\u00fcnlerin stok&#8217;lar\u0131 rezerve edildikten sonra, \u00f6deme i\u015flemi Payment Service&#8217;i taraf\u0131ndan ger\u00e7ekle\u015ftirilmektedir.<\/p>\n<p>Bu service i\u00e7erisinde \u00f6deme i\u015flemlerinin tetiklenebilmesi i\u00e7in &#8220;<em>StocksReservedEvent<\/em>&#8221; ini dinleyen a\u015fa\u011f\u0131daki gibi bir consumer bulunmaktad\u0131r.<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">public class StocksReservedEventConsumer : IConsumeAsync&lt;StocksReservedEvent&gt;\r\n{\r\n    private readonly IPaymentService _paymentService;\r\n    private readonly IBus _bus;\r\n\r\n    public StocksReservedEventConsumer(IPaymentService paymentService, IBus bus)\r\n    {\r\n        _paymentService = paymentService;\r\n        _bus = bus;\r\n    }\r\n\r\n    public async Task ConsumeAsync(StocksReservedEvent message, CancellationToken cancellationToken = default)\r\n    {   \r\n        Tuple&lt;bool, string&gt; isPaymentCompleted = await _paymentService.DoPaymentAsync(message.WalletId, message.UserId, message.TotalAmount);\r\n\r\n        if (isPaymentCompleted.Item1)\r\n        {\r\n            await _bus.PubSub.PublishAsync(new PaymentCompletedEvent\r\n            {\r\n                OrderId = message.OrderId\r\n            });\r\n        }\r\n        else\r\n        {\r\n            await _bus.PubSub.PublishAsync(new PaymentRejectedEvent\r\n            {\r\n                OrderId = message.OrderId,\r\n                Reason = isPaymentCompleted.Item2\r\n            });\r\n        }\r\n    }\r\n}<\/pre>\n<\/div>\n<p>Burada ise basit olarak \u00f6deme i\u015flemleri ger\u00e7ekle\u015ftirilmektedir. E\u011fer \u00f6deme i\u015flemi ba\u015far\u0131yla ger\u00e7ekle\u015ftirilirse, sipari\u015f&#8217;in durumunun Order Service taraf\u0131ndan <strong>completed<\/strong> olarak g\u00fcncellenebilmesi i\u00e7in &#8220;<em>PaymentCompletedEvent<\/em>&#8221; ad\u0131nda bir event publish edilmektedir.<\/p>\n<p>E\u011fer \u00f6deme i\u015flemi ba\u015far\u0131yla ger\u00e7ekle\u015ftirilemezse, &#8220;<em>PaymentRejectedEvent<\/em>&#8221; ad\u0131nda bir event publish edilmektedir. B\u00f6ylece Stock Service&#8217;i rezerve edilen \u00fcr\u00fcnlerin stok&#8217;lar\u0131n\u0131, \u00f6rnek business requirement&#8217;\u0131 gere\u011fi tekrardan release edebilmektedir.<\/p>\n<p>B\u00f6ylelikle sipari\u015f transaction&#8217;\u0131 distributed bir \u015fekilde u\u00e7tan uca loosely coupled ve consistent olarak tamamlanm\u0131\u015f olmaktad\u0131r.<\/p>\n<h2>Toparlayal\u0131m<\/h2>\n<p>Her design pattern&#8217;\u0131n spesifik bir business problemine bir \u00e7\u00f6z\u00fcm \u00f6nerisi getirdi\u011fi gibi, saga pattern&#8217;\u0131da bizlere distributed ortamlarda transaction y\u00f6netimi konusunda bir y\u00f6ntem sunmaktad\u0131r. Bu y\u00f6ntemin arkas\u0131ndaki temel mant\u0131k ise, bir dans ekibi i\u00e7erisindeki her bir \u00fcyenin bir ak\u0131\u015f ve uyum i\u00e7erisinde hareket ettikleri gibi uygulamalar\u0131m\u0131z\u0131n da bir ak\u0131\u015f ve uyum i\u00e7erisinde hareket etmelerine dayanmaktad\u0131r.<\/p>\n<p>Uygulanmas\u0131 her ne kadar basit bir pattern gibi g\u00f6r\u00fcnsede, elbette getirdi\u011fi baz\u0131 dez avantajlar\u0131\/zorlu y\u00f6nleri de bulunmaktad\u0131r.<\/p>\n<ul>\n<li>Sistem iyi bir \u015fekilde d\u00fc\u015f\u00fcn\u00fcl\u00fcp, her bir senaryo dikkatlice ele al\u0131nmal\u0131 ve ilgili tak\u0131mlar taraf\u0131ndan anla\u015f\u0131lmal\u0131d\u0131r.<\/li>\n<li>\u0130\u015flem zinciri i\u00e7erisindeki her bir service&#8217;in, ilgili compensating method&#8217;lar\u0131n\u0131 sa\u011flamas\u0131 gerekmektedir.<\/li>\n<li>\u0130\u015flem b\u00fct\u00fcnl\u00fc\u011f\u00fc event&#8217;ler vas\u0131tas\u0131yla ger\u00e7ekle\u015ftirilece\u011fi i\u00e7in, <strong>resiliency<\/strong> b\u00fcy\u00fck bir \u00f6nem ta\u015f\u0131maktad\u0131r. Bunun i\u00e7in <strong>outbox<\/strong> gibi pattern&#8217;lar yard\u0131m\u0131yla ilgili event&#8217;lerin ba\u015far\u0131yla publish edilebilmesi sa\u011flanmal\u0131d\u0131r.<\/li>\n<li>\u0130\u015flem zinciri i\u00e7erisine bir \u00e7ok farkl\u0131 service&#8217;in kat\u0131lmas\u0131 gerekti\u011fi durumlarda ise sistem kompleks bir hal almaya ba\u015flayabilir. Bu tarz durumlarda da choreography yerine orchestration yakla\u015f\u0131m\u0131n\u0131 tercih etmek daha do\u011fru bir yakla\u015f\u0131m olabilmektedir.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>G\u00fcn\u00fcm\u00fcz teknoloji \u00e7a\u011f\u0131nda neredeyse hepimiz microservice&#8217;ler hakk\u0131nda konu\u015fuyor ve uygulamalar geli\u015ftirmeye \u00e7al\u0131\u015f\u0131yoruz. Y\u00fczeysel bakt\u0131\u011f\u0131m\u0131zda her \u015fey \u00e7ok net ve uygulamas\u0131 kolay gibi g\u00f6r\u00fcnsede, \u00f6zellikle s\u00f6z konusu distributed transaction y\u00f6netimi oldu\u011funda i\u015fler daha karma\u015f\u0131k bir hal almaya ba\u015fl\u0131yor. \u00c7\u00fcnk\u00fc business&#8217;\u0131m\u0131z\u0131n sa\u011fl\u0131kl\u0131 bir \u015fekilde ilerleyebilmesini sa\u011flayabilmemiz ve&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/implementation-of-choreography-based-saga-in-dotnet-microservices\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">.NET Microservice&#8217;lerinde Choreography-based Saga<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":3734,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[505,68,417,285,368,152,47,1],"tags":[598,349,599,600],"class_list":["post-3707","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-core","category-architectural","category-asp-net-core","category-messaging","category-microservices","category-rabbitmq","category-tasarim-kaliplari-design-patterns","category-uncategorized","tag-net-core-saga","tag-saga","tag-saga-choreography","tag-saga-implementation","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":true,"content":true,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>.NET Microservice&#039;lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\".NET Microservice&#039;lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-21T20:47:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-02-22T16:04:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"675\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\".NET Microservice&#8217;lerinde Choreography-based Saga\",\"datePublished\":\"2021-02-21T20:47:39+00:00\",\"dateModified\":\"2021-02-22T16:04:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/\"},\"wordCount\":2331,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2021\\\/02\\\/choreography-based-saga.jpg\",\"keywords\":[\".net core saga\",\"Saga\",\"saga choreography\",\"saga implementation\"],\"articleSection\":[\".NET Core\",\"Architectural\",\"ASP.NET Core\",\"Messaging\",\"Microservices\",\"RabbitMQ\",\"Tasar\u0131m Kal\u0131plar\u0131 (Design Patterns)\",\"Uncategorized\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/\",\"name\":\".NET Microservice'lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2021\\\/02\\\/choreography-based-saga.jpg\",\"datePublished\":\"2021-02-21T20:47:39+00:00\",\"dateModified\":\"2021-02-22T16:04:53+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#primaryimage\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2021\\\/02\\\/choreography-based-saga.jpg\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2021\\\/02\\\/choreography-based-saga.jpg\",\"width\":1200,\"height\":675},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/implementation-of-choreography-based-saga-in-dotnet-microservices\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Implementation of Choreography-based Saga in .NET Microservices\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":".NET Microservice'lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/","og_locale":"tr_TR","og_type":"article","og_title":".NET Microservice'lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2021-02-21T20:47:39+00:00","article_modified_time":"2021-02-22T16:04:53+00:00","og_image":[{"width":1200,"height":675,"url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg","type":"image\/jpeg"}],"author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"15 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":".NET Microservice&#8217;lerinde Choreography-based Saga","datePublished":"2021-02-21T20:47:39+00:00","dateModified":"2021-02-22T16:04:53+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/"},"wordCount":2331,"commentCount":5,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg","keywords":[".net core saga","Saga","saga choreography","saga implementation"],"articleSection":[".NET Core","Architectural","ASP.NET Core","Messaging","Microservices","RabbitMQ","Tasar\u0131m Kal\u0131plar\u0131 (Design Patterns)","Uncategorized"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/","url":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/","name":".NET Microservice'lerinde Choreography-based Saga - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#primaryimage"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg","datePublished":"2021-02-21T20:47:39+00:00","dateModified":"2021-02-22T16:04:53+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/"]}]},{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#primaryimage","url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2021\/02\/choreography-based-saga.jpg","width":1200,"height":675},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/implementation-of-choreography-based-saga-in-dotnet-microservices\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"Implementation of Choreography-based Saga in .NET Microservices"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=3707"}],"version-history":[{"count":5,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3707\/revisions"}],"predecessor-version":[{"id":3737,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/3707\/revisions\/3737"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media\/3734"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=3707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=3707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=3707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}