Week 2 (July 2026)

This page contains my work log for July 8–15, 2026.

Tasks

Wednesday, July 8, 2026

ShardingSphere: support split function

Pull Request: https://github.com/apache/shardingsphere/pull/39056

Issue 31509 is still unresolved because the split_by_string function is not yet supported by the parser engine.

I resolved it by creating the above pull request so that the Kernel Parser Engine supports that function for the Doris database.

As a result, the split_by_string function is now supported by the changes in this pull request. Details below:

image


Thursday, July 9, 2026


Friday, July 10, 2026

Electron: Cross-platform Desktop Apps

The stakeholder has a dashboard, built as an HTML file, which they created using Claude. They asked us to modify their HTML file so that it can connect to the dataset. Therefore, It can preview the actual data instead of dummy data.

The actions taken were: the dashboard was modified to connect to the dataset, and the HTML file was rendered as an executable, for reasons that can't be disclosed.

I created the executable file using Electon because I'm only familiar with this tool. The methods for building the executable file are below:

Step 1. Create a main.js file, and load the index.html file into the window.

const { app, BrowserWindow } = require('electron');
function createWindow() {
    const win = new BrowserWindow({ width: 1000, height: 700 });
    win.loadFile('index.html');
    win.setMenu(null);
}
app.whenReady().then(createWindow);

Step 2. Modify the package.json file to support building for Windows and macOS platforms.

{
  "name": "stakeholder-dashboard",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "build": "electron-builder --mac --win",
    "build:mac": "electron-builder --mac",
    "build:win": "electron-builder --win"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "devDependencies": {
    "electron": "^43.1.0",
    "electron-builder": "^26.15.3"
  },
  "build": {
    "appId": "com.stakeholder.dashboard",
    "productName": "stakeholder-dashboard",
    "files": [
      "main.js",
      "index.html"
    ],
    "mac": {
      "target": [
        {
          "target": "dmg",
          "arch": [
            "arm64",
            "x64"
          ]
        }
      ],
      "category": "public.app-category.business"
    },
    "win": {
      "target": [
        {
          "target": "nsis",
          "arch": [
            "x64"
          ]
        }
      ]
    }
  }
}

Step 3. Build the executable files with command below:

$ npm run build       # Build for both operating system
$ npm run build:mac   # Build for macOS
$ npm run build:win   # build for Windows

As a result, the dashboard is now preview the actual data, and it can run in the Windows and macOS as an executable file.


Saturday, July 11, 2026

ShardingSphere: Parse Doris SQL

Pull Request: https://github.com/apache/shardingsphere/pull/39056

My pull request got a comment from Liang Zhang. He requested a change because my implementation was wrong. The problem is that it was not preserves expression arguments in SPLIT_BY_STRING. Details below:

@Override
public final ASTNode visitSplitByStringFunction(final SplitByStringFunctionContext ctx) {
    FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.SPLIT_BY_STRING().getText(), getOriginalText(ctx));
    for (ExprContext each : ctx.expr()) {
        result.getParameters().add(new LiteralExpressionSegment(each.getStart().getStartIndex(), each.getStop().getStopIndex(), each.getText()));
    }
    return result;
}

The above function will accept the following query, and it's wrong. (Details: here)

SELECT SPLIT_BY_STRING("hello world", "-", ?, ?);

I addressed the comment by reusing getExpressions(ctx.expr()). Details below:

@Override
public final ASTNode visitSplitByStringFunction(final SplitByStringFunctionContext ctx) {
    FunctionSegment result = new FunctionSegment(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex(), ctx.SPLIT_BY_STRING().getText(), getOriginalText(ctx));
    result.getParameters().add(new LiteralExpressionSegment(ctx.expr(0).getStart().getStartIndex(), ctx.expr(0).getStop().getStopIndex(), ctx.expr(0).getText()));
    result.getParameters().add(new LiteralExpressionSegment(ctx.expr(1).getStart().getStartIndex(), ctx.expr(1).getStop().getStopIndex(), ctx.expr(1).getText()));
    return result;
}

As a result, the CI Pipeline passed, and I'm waiting for him to take another look.

Debezium Example: PR#423

Pull Request: https://github.com/debezium/debezium-examples/pull/423

Vincenzo raised a concern in the pull request because I re-imported the Quarkus BOM in the cache-invalidation module. This isn't correct, since it's already imported in the parent POM. I did this to pin JUnit 5 so it runs in this module instead of JUnit 6.

That said, He was right, and I need to address it.

I addressed it by removing the Quarkus BOM from the cache-invalidation POM's dependency management. And, re-order the dependencies on the parents POM. Details below:

Before:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
            <groupId>io.debezium</groupId>
            <artifactId>debezium-bom</artifactId>
            <version>${version.debezium}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-bom</artifactId>
            <version>${version.quarkus}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

After:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-bom</artifactId>
            <version>${version.quarkus}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>io.debezium</groupId>
            <artifactId>debezium-bom</artifactId>
            <version>${version.debezium}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

This ordering matters because JUnit 5 takes priority over JUnit 6 from the Debezium BOM.

As a result, the CI pipeline for the cache-invalidations module passed, and I'm waiting for him to take another look.


Sunday, July 12, 2026

AI Infra: llm-d

Article: Introduction to distributed inference with llm-d

Problems and Challenges:

I measure the LLM Inference performance by monitoring metrics such as CPU utilization, Memory consumption, HTTP Request counts, etc. This conventional approach do not fully capture LLM behavior, and become inadequate.

The inference system rely on generic routing strategies such as Round Robin and Sticky Sessions, both of which were designed for Web traffic, not LLMs. These strategies do not account for prompt structure, token count, queue depth, and GPU load. Also, These strategies fail to reuse the cache computation efficiently.

llm-d in actions

The three core areas:

  1. Disaggregated inference
  2. Cache-aware routing
  3. Mixture of Experts

Disaggregated inference

In LLMs, there are two stages: the prefill phase and the decode phase. The prefill phase processes the input tokens and computes the KV cache. The decode phase generates the output tokens. The disaggregated inference method is able to handle these processes effectively.

Below is an illustration of the LLM stages, where prompt processing produces a KV cache, which is sent to the decode phase to generate the output.

Request -> Prompt processing (prefill) -> KV Cache -> Token Generation (Decode) -> Output

If a GPU is not available, llm-d allows the prefill phase to run on CPUs while the decode phase runs on GPUs. The decode phase is typically more memory-intensive, and it can benefit from GPU acceleration. On the other hand, the prefill phase can often be handled effectively with a CPU.

As a result, llm-d uses disaggregated inference rather than Round Robin to improve LLM performance through routing.

Cache-aware routing

llm-d introduce inference gateway for understanding the structure and content of incoming prompts, after that it route them based on cache context and prior requests.

For example, consider user who requests a summary of financial report. If the same prompt has already been processed, the inference gateway will route to the relevant cache. This reduces redundant computation, improve time to first token, and lowers GPU usage. Details below:

image

Mixture of Experts

This approach introduces two forms of parallelism: Expert Parallelism (EP) and Data Parallelism (DP).

In short, the expert parallelism able breaks the model into specialized components. This avoids relying on a single large GPU machine. Instead, llm-d makes it possible to use multiple smaller nodes, often with mixed hardware, to scale horizontally across the entire datacenter.

For example, consider we use the GPT-OSS model, which is broken into several experts such as math and biology. If the inference gateway receives an incoming prompt about math, it will be routed to the math expert, which runs on a machine with more GPUs. On the other hand, if it receives a prompt about biology, it will be routed to the relevant expert, and run on a machine with fewer GPUs.

Details below:

image


Monday, July 13, 2026

Personal Website: Open Source Contribution

I’d like to create a page on my personal website to showcase my contributions to the open-source project. The page should be a concise list of the pull requests I’ve made on the projects below:

I created the contribution page, which consists solely of a navigation bar and tables containing the pull requests. The style of this page inspired from the Zig documentation page.

As a result, the contribution page is now available. Find out below:

contribution page: https://ilyasahsan.xyz/contributions


Tuesday, July 14, 2026

GitHub: Repository Migration — Kubernetes

I need to migrate this repository, and it's CI/CD pipeline to GitHub. This is important so that our operations in deploying services to Kubernetes continue. The difficult part is that migrating the CI/CD pipeline, because it's used legacy approach for GitOps in Kubernetes.

The actions were creating a dedicated service account, and preparing GitHub self-hosted runner that able connects with the Kubernetes cluster. and, I’m currently working on converting the CI/CD scripts from GitLab CI to GitHub Actions.

This task might be taken a lot of time.