Posts

View Categories

  • Waiting until Docker containers are initialized

    An issue that a lot of people run into when automating Docker builds is in figuring out how to wait for services to be set up before running subsequent commands.

    For example, you might need your database container to finish initializing before you can run your database migrations and test scripts.

    A common solution is to add wait times between steps, adjusting times as necessary. Another solution is to continuously ping the containers to check for open ports or specific files that are created during set up.

    Neither strategy is ideal. Fixed wait times are at best unnecessarily long and at worst lead to fragile builds, and open ports and created files don’t reliably indicate that a Docker container is fully initialized.

    A third strategy that has been suggested for database containers is to query the database every few seconds until it has been set up with the required user credentials.

    Continue reading...

  • Dijkstra's algorithm for finding the shortest path to other nodes

    Dijkstra's algorithm is a simple, elegant graph algorithm, and one of my favourites.

    The problem it solves is the following: given a graph with non-negative edge weights and a start node, how can we find the shortest path to other nodes in the graph?

    Continue reading...

  • (LXDE) Adding user-specific start menu items

    In this post we’ll add a user-specific start menu item for an npm application, Evolus Pencil V3.

    To create a start menu item with a custom icon, we will:

    1. Define the start menu item in a .desktop file
    2. Add an icon to the filepath specified in the .desktop file
    3. Refresh the start menu to view our changes

    Continue reading...

  • Scalability of data processing

    How can we make distributed computing more resilient, remove bottlenecks, and improve scalability?

    We can often address these questions at the architectural design level, in which we plan the structure of our system and the high-level interactions between system components.

    Continue reading...

  • Hash functions for cryptography versus look-up

    A hash function accepts an arbitrary sequence of bits, such as a string or file, and outputs a corresponding sequence of bits of fixed size. This output is known as the "hash" of the input.

    Continue reading...

  • Simple Git workflows for teams

    There are several common workflows for managing projects using Git, and which one works best will depend on your team’s structure and the complexity of your project.

    If you deploy frequently, you may benefit from a structure that maintains an always-stable branch to release from, while allowing developers to work on unstable features. If you don’t host your products on your own servers, but instead have customers download software to install themselves, you may have to maintain multiple release branches that you can apply hot-fixes to.

    Continue reading...

  • Types of failures in distributed systems

    Failure recovery is an interesting problem in many applications, but especially in distributed systems, where there may be multiple devices participating and multiple points of failure.

    It’s very educational to identify the distinct roles in a system, and ask for each one, “What would happen if that part of the system failed?”

    Continue reading...

  • Golang channels

    The Go Programming Language has built-in communication channels, which provide type-safe one-way or two-way communication between processes. This can be very useful for concurrent programming, such as in master-slave and map-reduce programs.

    Channels can be buffered or unbuffered, where buffered channels can store multiple messages up to a declared capacity. Once a channel is full, it blocks further writes until a process initiates a read operation.

    Continue reading...


subscribe via RSS