Menjalankan sistem worker queue terdistribusi di lingkungan heterogen yang melibatkan node x86_64 atau ARM64 bersama IBM Z (s390x) memicu risiko bug korupsi data payload biner. x86_64 beroperasi menggunakan format little-endian (byte berbobot rendah disimpan di alamat memori terendah), sedangkan arsitektur s390x mengimplementasikan big-endian (byte berbobot tinggi disimpan lebih dahulu). Ketidakcocokan representasi memori ini merusak payload numerik pada antrean pesan seperti Redis Streams atau RabbitMQ jika serialisasi dilakukan melalui transfer memori mentah.

Root Cause: Korupsi Data pada Binary Payload Worker

Masalah utama muncul ketika producer dan consumer mengabaikan tata letak byte (byte order) saat membaca atau menulis struct langsung ke socket antrean.

Misalnya, producer mengirim struct job ID 32-bit integer bernilai 1 (hex: 0x00000001):

  • Pada x86_64 (Little-Endian), urutan byte di memori: 0x01 0x00 0x00 0x00
  • Ketika payload raw memory tersebut dipush ke Redis dan di-dequeue oleh worker s390x (Big-Endian), worker membaca 4 byte tersebut secara berurutan dari memori.
  • Worker s390x membaca urutan 0x01 0x00 0x00 0x00 sebagai nilai 16,777,216 (0x01000000).

Kesalahan fatal ini terjadi pada kode C, Go, Python (modul struct), atau Rust yang menggunakan memory reinterpretation tanpa konversi protokol wire.

Penyelesaian: Menggunakan Network Byte Order

Solusi standar komunikasi jaringan adalah menetapkan Network Byte Order (selalu Big-Endian) untuk seluruh binary payload di broker antrean. Semua tipe data multi-byte wajib dikonversi sebelum serialisasi dan sesudah deserialisasi.

Berikut contoh implementasi deserializer biner deterministik di Go untuk worker s390x dan x86_64:

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

// JobPayload mendefinisikan layout data mentah 12 byte
type JobPayload struct {
	JobID  uint32 // 4 byte
	UserID uint32 // 4 byte
	Amount uint32 // 4 byte
}

// EncodePayload mengubah struct menjadi byte stream Big-Endian
func EncodePayload(job JobPayload) ([]byte, error) {
	buf := new(bytes.Buffer)
	// Selalu gunakan binary.BigEndian independen terhadap CPU host
	if err := binary.Write(buf, binary.BigEndian, job); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

// DecodePayload membaca byte stream Big-Endian ke struct target
func DecodePayload(data []byte) (JobPayload, error) {
	var job JobPayload
	reader := bytes.NewReader(data)
	if err := binary.Read(reader, binary.BigEndian, &job); err != nil {
		return job, err
	}
	return job, nil
}

Alternatif: Gunakan format serialisasi standar skema seperti Protocol Buffers (Protobuf) atau MessagePack. Library encoder kedua format tersebut menangani representasi integer endianness secara internal pada level wire specification.

Testing Deterministik Lintas Arsitektur

Unit test harus memvalidasi kesesuaian serialisasi tanpa mengandalkan arsitektur host lokal. Uji byte array mentah secara langsung dengan tabel hex statis.

package main

import (
	"bytes"
	"testing"
)

func TestPayloadSerializationEndianness(t *testing.T) {
	job := JobPayload{
		JobID:  1,
		UserID: 42,
		Amount: 500,
	}

	// 1 = 0x00000001, 42 = 0x0000002A, 500 = 0x000001F4
	expectedWireBytes := []byte{
		0x00, 0x00, 0x00, 0x01, // JobID
		0x00, 0x00, 0x00, 0x2A, // UserID
		0x00, 0x00, 0x01, 0xF4, // Amount
	}

	encoded, err := EncodePayload(job)
	if err != nil {
		t.Fatalf("Gagal encode: %v", err)
	}

	if !bytes.Equal(encoded, expectedWireBytes) {
		t.Fatalf("Endianness mismatch. Got %x, want %x", encoded, expectedWireBytes)
	}

	decoded, err := DecodePayload(expectedWireBytes)
	if err != nil {
		t.Fatalf("Gagal decode: %v", err)
	}

	if decoded != job {
		t.Fatalf("Struct mismatch. Got %+v, want %+v", decoded, job)
	}
}

Emulasi dan Validasi CI/CD s390x

Verifikasi pipeline pengujian s390x tanpa hardware mainframe fisik dapat dilakukan menggunakan QEMU User-Mode Emulation di Docker container x86_64:

# Registrasi binary handler binfmt_misc di host x86_64
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

# Jalankan test suite langsung di environment s390x container
docker run --rm -v $(pwd):/workspace -w /workspace s390x/golang:latest go test -v ./...

Pengujian emulasi ini memastikan decoding byte biner berjalan identik baik di node worker x86_64 maupun node mainframe s390x sebelum deployment.