Skip to content
Go back

My Naive implementation of no-code/low-code tool

Introduction

In recent years, the popularity of no-code/low-code tools has skyrocketed, with more and more individuals and organizations looking for ways to simplify their development processes.

As a software engineer, I am intrigued by these tools and have been exploring their inner workings. In this article, I want to share my learning and provide a naive implementation of such tools.

The main characteristic of no-code/low-code tools is custom Domain Specific Language (DSL). Most tools have their own schema, of which it provides information of how the workflow should be run.

Following is an example of workflow in n8n that backup n8n workflows to google drive.

https://n8n.io/workflows/1150-backup-n8n-workflows-to-google-drive/

In a workflow, each action can be represented as a node in a graph, with each node having its own input, output, and execution logic. Nodes that are connected indicate that data will be passed between them.

Temporal

I recently came across an open-source tool called Temporal, which is focused on providing first-class support for workflows in a distributed environment. By managing the execution of workflows and activities, Temporal simplifies the development process and makes it easier for developers to build fault-tolerant and scalable applications.

Temporal UI

At its core, Temporal consists of two important concepts: activities and workflows. Activities are units of work such as calling an external API or running a database query, while workflows are a series of coordinated activities that form a business process. Workflows manage the state and execution of activities, providing a powerful framework for building scalable and fault-tolerant distributed applications.

Temporal seems to be the perfect tool for my experiments in writing a naive implementation of no-code/low-code application.

The primary goal of this implementation is to establish a straightforward domain-specific language (DSL) using YAML to accurately define workflows and activities in Temporal. We will use encore.dev as framework.

Domain Specific Language (DSL)

The YAML DSL structure for our workflow consists of nodes representing actions, while connections indicate the sequence of workflow execution.

name: my-workflow
description: This is an example workflow.

nodes:
  - name: SampleActivity1
    type: activity
    input:
      main:
        - SA1Value1
        - SA1Value2
  - name: SampleActivity2
    type: activity
  - name: SampleActivity3
    type: activity
  - name: SampleActivity4
    type: activity

connections:
  - from: SampleActivity1
    to:
      - SampleActivity2
      - SampleActivity3
      - SampleActivity4
  - from: SampleActivity2
    to:
      - SampleActivity3
  - from: SampleActivity4
    to:
      - SampleActivity2

Visualizing workflowย yaml

The assumption made here is that the graph representing the workflow should always be a Directed-Acyclic Graph. Using topological sort, we can accurately determine the sequence of execution.

Implementation

Firstly, we define each activity. Currently, it is doing simple logging and returning some strings as output.

Next, we need to define how to parse our DSL YAML as a struct in go. yaml.Unmarshal from the official library comes in handy here.

Lastly, we need to be able to define a workflow in runtime based on the WorkflowData struct. Topo-sort is used to determine the order of execution. Itโ€™s also assumed that the output of each activity is passed as input to the next one.

To keep it simple, the engine will parse the YAML file during startup, register the workflow with Temporal, and execute it immediately. We can check execution logs of activities to verify that the workflow is running correctly.

Application Logs

Output Activities in Temporalย UI

The code is available on GitHub


Share this post on:

Previous Post
Bringing Pattern Matching to Go
Next Post
MySejahtera is a Perfectly Good App With No Exploits