<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Silva Chijioke Michael</title>
    <description>The latest articles on Forem by Silva Chijioke Michael (@chijiooke).</description>
    <link>https://forem.com/chijiooke</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F828683%2F2c4b2bf2-46a9-4d4c-aeb8-c03384c5b719.png</url>
      <title>Forem: Silva Chijioke Michael</title>
      <link>https://forem.com/chijiooke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chijiooke"/>
    <language>en</language>
    <item>
      <title>"depends_on" vs "wait-for-it.sh" in Docker Compose</title>
      <dc:creator>Silva Chijioke Michael</dc:creator>
      <pubDate>Thu, 25 Sep 2025 05:21:08 +0000</pubDate>
      <link>https://forem.com/chijiooke/dependson-vs-wait-for-itsh-in-docker-compose-30jd</link>
      <guid>https://forem.com/chijiooke/dependson-vs-wait-for-itsh-in-docker-compose-30jd</guid>
      <description>&lt;p&gt;When working with multi-container setups (for example, an application and a database), it’s important to understand the difference between &lt;strong&gt;container startup order&lt;/strong&gt; and &lt;strong&gt;service readiness&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;depends_on&lt;/code&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ensures a container &lt;strong&gt;starts before&lt;/strong&gt; another.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: Your app won’t start until the database container has been launched.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limitation&lt;/strong&gt;: It does &lt;strong&gt;not&lt;/strong&gt; guarantee the database is ready to accept connections.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;wait-for-it.sh&lt;/code&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A lightweight shell script that makes one service &lt;strong&gt;wait until another is reachable&lt;/strong&gt; (via TCP).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["wait-for-it", "db:5432", "--", "npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures the app starts &lt;strong&gt;only after Postgres is ready&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Visual Comparison
&lt;/h2&gt;

&lt;p&gt;Without &lt;code&gt;wait-for-it.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App ----&amp;gt; tries DB   [DB not ready]   → fails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;wait-for-it.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App ----&amp;gt; waits ----&amp;gt; DB ready        → starts successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why prefer &lt;code&gt;wait-for-it.sh&lt;/code&gt; (or similar scripts)?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prevents race conditions such as applications crashing on startup.&lt;/li&gt;
&lt;li&gt;Works across any service (databases, caches, APIs).&lt;/li&gt;
&lt;li&gt;Simple, portable, and avoids complex retry logic in your application code.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;code&gt;depends_on&lt;/code&gt;&lt;/strong&gt; for container startup order.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;code&gt;wait-for-it.sh&lt;/code&gt;&lt;/strong&gt; (or healthchecks) for service readiness.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This small distinction saves time, prevents bugs, and ensures smoother container orchestration.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Ensuring Idempotency in Distributed Systems – Lessons from Go &amp; GCP</title>
      <dc:creator>Silva Chijioke Michael</dc:creator>
      <pubDate>Mon, 25 Aug 2025 05:11:04 +0000</pubDate>
      <link>https://forem.com/chijiooke/ensuring-idempotency-in-distributed-systems-lessons-from-go-gcp-386g</link>
      <guid>https://forem.com/chijiooke/ensuring-idempotency-in-distributed-systems-lessons-from-go-gcp-386g</guid>
      <description>&lt;p&gt;In distributed systems, failures happen — network glitches, retries, or even duplicate requests. Without proper handling, this can lead to unintended side effects like multiple charges, duplicated tasks, or inconsistent states.&lt;/p&gt;

&lt;p&gt;This is where &lt;em&gt;&lt;strong&gt;idempotency&lt;/strong&gt;&lt;/em&gt; comes in.&lt;/p&gt;

&lt;p&gt;Idempotency means that performing the same operation multiple times produces the same result, no matter how many retries occur. Think of pressing an elevator button — pressing it once or ten times doesn't make the elevator arrive faster; the action has the same effect.&lt;/p&gt;

&lt;p&gt;Recently, we refactored parts of our system to ensure idempotency across critical operations. Using Go and Google Cloud Platform (GCP) services like Pub/Sub, we introduced queues and deduplication strategies that guarantee:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No duplicate processing&lt;/strong&gt;: We track request IDs to ensure each request is processed only once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safe retries&lt;/strong&gt;: If a worker crashes or a request times out, retries don't break consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic outputs&lt;/strong&gt;: The same inputs always produce the same result.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;A few lessons learned&lt;/strong&gt;:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Design for retries&lt;/strong&gt;: Assume every call may happen more than once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use queues&lt;/strong&gt;: use queues with at-least-once delivery (e.g., Pub/Sub) but build deduplication logic into your service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep business logic deterministic&lt;/strong&gt;: avoid side effects like random values unless controlled.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implementing idempotency might feel like extra work, but it’s essential for building resilient, fault-tolerant systems, especially at scale.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you implemented idempotency in your APIs or distributed workflows? How did you handle retries and deduplication?&lt;/p&gt;

</description>
      <category>go</category>
      <category>gcp</category>
      <category>softwareengineering</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Solving simple time based problems with go lang.</title>
      <dc:creator>Silva Chijioke Michael</dc:creator>
      <pubDate>Mon, 13 May 2024 11:25:33 +0000</pubDate>
      <link>https://forem.com/chijiooke/solving-simple-time-based-problems-with-go-lang-3gap</link>
      <guid>https://forem.com/chijiooke/solving-simple-time-based-problems-with-go-lang-3gap</guid>
      <description>&lt;p&gt;so interestingly i was assigned a task i really enjoyed, this had to do with repeatedly looping over a set of documents in the db, making some transactions and finally updating documents based on certain conditions.&lt;br&gt;
The first idea was to use a Cron Job(well obviously) everyone knows what a cron job does, but interestingly the problem was to be solved using Go Lang which is one of our stacks on my current team.&lt;/p&gt;

&lt;p&gt;I shared the problem with the backend team and we discussed different methods to approach the problem and at the end of the day it boiled down to setting up a cron job that runs repeatedly at “x time” or using the Go timer package.&lt;/p&gt;

&lt;p&gt;I used the go timer package and i used it mainly for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of use:&lt;/strong&gt; it was already pre-installed, easy to use and provides a plethora of methods and properties that could be used to solve basically all the problems presented on a low level (it gives total control)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less complexity:&lt;/strong&gt; I was already using go lang, there was no real need to install a separate package to over engineer a somewhat simple problem.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s a simple snippet of how to solve the same type of problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We define our timed funtion
for this example we'll be using the go MongoDB and mux router
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// assuming we want the function to run at 12am daily
func initTimer(conn *db.MongoDB, router *mux.Router) {
    currentTime := time.Now()

    // Calculate the duration until 12 AM
    desiredTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), 0, 0, 0, 0, currentTime.Location())
    if desiredTime.Before(currentTime) {
        // If 12AM has already passed today, schedule it for 12AM tomorrow
        desiredTime = desiredTime.Add(24 * time.Hour)
    }

    // Calculate the duration until the 12AM
    duration := desiredTime.Sub(currentTime)

    // Wait until it's time to execute the function
    &amp;lt;-time.After(duration)
    go ourTransaction(conn, router)
}

func ourTransaction(conn *db.MongoDB, router *mux.Router) {
   entity := pkg.InitTrxn(conn, router) //init package


    //initial transaction to counter build during updates (optional)
    go entity.RunTrxn()

    // re-run this function every 24hrs by setting up a new ticker using the "time.NewTicker" function
    var ticker *time.Ticker = time.NewTicker(24 * time.Hour)

    //repeat actions at intervals using the "ticker.C" field
    for tickTime := range ticker.C {
        go entity.RunTrxn() // a resource intensive function
        log.Println("i'm running at time:", tickTime)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We initialize the timed functions in our main.go package
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main(){
// initialize 
    go initTimer(dbConn, router) // run on a separate thread 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In my case the the transaction needed me to make an update base on last action time (..actally i just want to show more stuff done with the go timer package 😏).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package packageName

func (t trxnStruct) RunTrxn() {
       items, err := t.GetAllItems()
       if err != nil{
          log.Panicf("Error at getting items %s", err)
          }

       for _, item := range items {

       // get time difference between last transaction time  and current time using the "time.since" function
         timeDifferenceSinceLastTrxn = time.Since(item.LastTransactionTime)

        inActiveDays := int(timeDifferenceSinceLastTrxn.Hours() / 24) //convert to days
        item.InActiveDays = inActiveDays
         maxdaysofInactivity := 10 

        if item.InActiveDays &amp;gt; maxdaysofInactivity{
           item.Status = constants.INACTIVE 
          }

        t.UpdateItem(item.ID, item) // repo funtion to update DB Record

      }
   return
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, the go timer package is a robust and yet easy to use package with a lot of useful tools to help solve your time based based problems. you can find more info from the docs [&lt;a href="https://pkg.go.dev/time" rel="noopener noreferrer"&gt;https://pkg.go.dev/time&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>How I built a multiplayer game with no backend</title>
      <dc:creator>Silva Chijioke Michael</dc:creator>
      <pubDate>Tue, 05 Dec 2023 19:48:50 +0000</pubDate>
      <link>https://forem.com/chijiooke/how-i-built-a-multiplayer-game-with-no-backend-2g62</link>
      <guid>https://forem.com/chijiooke/how-i-built-a-multiplayer-game-with-no-backend-2g62</guid>
      <description>&lt;h1&gt;
  
  
  Crafting Multiplayer X and O Game: A WebSuckit Adventure
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;Join me on a journey into the world of multiplayer online games as we dive into creating a WebSocket-powered tic-tac-toe game. This article aims to demystify the process and provide a hands-on guide for building a real-time gaming experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Picture this: You built a game about two, three years ago as a yearly vanilla javascript refresher. This was a simple tic-tac-toe game that manipulated arrays, objects, and the browser Dom and this was forgotten somewhere in your GitHub with a "To Do" comment that read "Make this a multiplayer Game".&lt;/p&gt;

&lt;p&gt;Fast forward a couple of months into 2023, you reached out to a couple of friends and you get to find out they've been working on a duplex communication platform for developers and there's a need for example projects, and voila! out of the plethora of unfinished chat apps, you remember the "To Do" comment this was almost as perfect as Lee laying that first kick on Gara's head in the season 1 of the Naruto series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Set the Scene
&lt;/h2&gt;

&lt;p&gt;Before we jump into the coding magic, let's set the stage. Why WebSocket, you ask? Well, WebSocket enables seamless communication between clients and servers, making it ideal for creating responsive and interactive multiplayer games but then I had no intentions of setting up a backend server for the project, I didn't even run a 'node init'.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;There were three major challenges, the first was setting up a connection to the native websocket server, the second was managing the logic for the first connection between the initializer and others joining using his URL, and finally managing and communicating disconnections.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Behind the Magic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  WebSuckit 101
&lt;/h3&gt;

&lt;p&gt;First things first, let's get familiar with the star of the show: WebSuckIt. This section serves as your crash course, so buckle up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up the Playground
&lt;/h3&gt;

&lt;p&gt;Time to get our hands dirty. We'll set up the environment, initialize the game engine, and lay the foundation for our multiplayer masterpiece.&lt;/p&gt;

&lt;p&gt;firstly we introduced our package in our HTML file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;script src="https://unpkg.com/@websuckit/js/dist/websuckit.umd.js"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we instantiate a websuckit class, to do this we simply had to create an account on websuckit&lt;a href="https://websuckit.com" rel="noopener noreferrer"&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;navigated to our profile and copied out the necessary credentials required to initialize our class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const config = {
  PUBLIC_KEY: "your public key",
  USER_ID: "your user ID",
  ACCESS_KEY: "your access key",
};

//ws - Our websuckit class 
const ws = new Websuckit({
  userId: config.USER_ID,
  accessKey: config.ACCESS_KEY,
  publicKey: config.PUBLIC_KEY,
});`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Gameplay
&lt;/h2&gt;

&lt;p&gt;With the stage set and the tech in place, let the gameplay commence. We'll break down the technical details into bite-sized chunks, exploring each aspect of our game.&lt;/p&gt;

&lt;h3&gt;
  
  
  Player X vs. Player O
&lt;/h3&gt;

&lt;p&gt;Delve into the intricacies of player interactions. How does the game react when Player X makes a move? How about Player O? We've got it covered.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Thrill of Victory, the Agony of Defeat
&lt;/h3&gt;

&lt;p&gt;Explore the logic behind determining a winner or declaring a draw. After all, every game needs a champion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing It to Life
&lt;/h2&gt;

&lt;p&gt;Enough theory; let's bring our creation to life. Follow along as we implement the game, step by step. By the end, you'll have a functioning multiplayer tic-tac-toe game to call your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in It for You?
&lt;/h2&gt;

&lt;p&gt;Wondering why you should embark on this WebSocket adventure? We'll uncover the benefits, the skills you'll gain, and the sheer joy of seeing your creation in action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Lessons
&lt;/h2&gt;

&lt;p&gt;Every adventure comes with its challenges. We'll navigate through potential pitfalls and share the lessons learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As our WebSocket journey comes to an end, take a moment to reflect on the incredible world of real-time gaming you've just stepped into. Cheers to the countless multiplayer adventures that lie ahead!&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Fun
&lt;/h2&gt;

&lt;p&gt;Ready to embark on your WebSocket journey? Dive into the code, explore the nuances, and bring your own twist to this multiplayer gaming saga. Let the games begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;Meet [Your Name], a passionate developer with a knack for turning complex concepts into engaging adventures. Connect on [LinkedIn/Twitter/GitHub] for more coding escapades.&lt;/p&gt;




&lt;p&gt;Feel free to personalize and adapt this template to match your style and the specific details of your WebSocket gaming experience. Happy writing!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>websuckit</category>
    </item>
  </channel>
</rss>
