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

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

With Temporal and Encore

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

Republished from
https://medium.com/@PhakornKiong/my-naive-implementation-of-no-code-low-code-tool-253e678f2456