Skip to content

[ND-319/LNSW.34/2026] Penyesuaian Durasi Submission Cooldown 60 Detik, Auto-Release Lock Redis, dan Null-Safety Data NIB Pengajuan PAB

Modul: SIPT/PAB | Tipe: Bugfix | Stage Saat Ini: DEVELOPMENT | Tanggal Dokumen: 2026-08-24


1. Informasi Tugas & Referensi Bisnis

  • Task ID / Nomor Referensi: ND-319/LNSW.34/2026
  • Sumber Instruksi: Nota Dinas Resmi ND-319/LNSW.34/2026
  • Dokumen Referensi / Lampiran: Permohonan Perbaikan Bug pada Aplikasi PAB.pdf (tersimpan pada direktori attachments jika ada)
  • Modul Terkait: SIPT/PAB
  • Service / Repository: sipt-backend
  • PIC Pengembang: Hermansyah Efendi / Muhamad Firly Ramadan
  • Latar Belakang & Ringkasan Kebutuhan: Berdasarkan evaluasi operasional dan laporan bug pada Nota Dinas ND-319/LNSW.34/2026 terkait aplikasi PAB (Pemberitahuan Arus Barang):
    1. Durasi submission cooldown pengajuan PAB sebelumnya bernilai 5 menit (300 detik) yang dinilai terlalu lama bagi pengguna ketika pengajuan membutuhkan pengiriman ulang atau saat terjadi error jaringan. Selain itu, lock Redis sebelumnya tidak langsung dilepas jika request selesai lebih awal atau terjadi kegagalan sistem, menyebabkan user tertahan cooldown yang tidak perlu.
    2. Terjadi runtime error TypeError: Cannot read properties of undefined (reading 'trim') pada modul integrasi eksternal Kemendag dan skema validasi Zod ketika memproses data pelaku usaha yang memiliki nilai nib atau nib_penerima bernilai kosong (null/undefined). Proses bisnis PAB mengizinkan data NIB Forwarder (Ekspedisi) maupun Penerima kosong, sehingga diperlukan penanganan null-safety komprehensif.

2. Deployment Lifecycle

#EnvironmentTanggal & WaktuPICStatusCatatan
1Development2026-08-24 13:43Hermansyah Efendi / Muhamad Firly RamadanDEPLOYEDBranch: development (Commit: ebd871dc)
2Staging (UAT)PENDING
3ProductionPENDING

Riwayat Update Log

TanggalEnvironmentPerubahanPIC
2026-08-24DevelopmentInisialisasi draft audit log dari context block backend (commit ebd871dc)Hermansyah Efendi / Muhamad Firly Ramadan

3. Analisis Teknis & Rincian Perubahan

  • Alur Logika & Bisnis:

    • Optimasi Middleware Cooldown & Lifecycle Lock Redis (app/middlewares/submission_cooldown.js):
      • Mengurangi konstanta COOLDOWN_SECONDS dari 300 detik (5 menit) menjadi 60 detik (1 menit).
      • Mengimplementasikan monkey-patching pada lifecycle response Express (res.end) agar otomatis memicu fungsi releaseLock() yang mengeksekusi redisClient.del(cacheKey) saat request selesai (finish/close maupun error). Hal ini menjamin lock hanya menahan konkurensi selama proses berlangsung dan langsung dibebaskan pasca-eksekusi tanpa menunggu TTL habis.
    • Null-Safety Integrasi Kemendag (app/api/kemendag.api.js):
      • Menambahkan optional chaining operator (?.trim()) pada pemetaan payload ekspedisi.nib dan penerima.nib_penerima saat pembentukan payload JSON integrasi Kemendag guna mencegah crash saat data bernilai null atau undefined.
    • Null-Safety Penanganan Pembatalan Pengajuan (app/controllers/newsend_sipt_controller.js):
      • Penanganan null-safety parameter pada pembatalan pengajuan PAB untuk menjamin konsistensi payload sebelum diteruskan ke service layer.
    • Validasi Zod Schema & Whitelist Rule (app/helpers/zod.js & app/validations/pelaku_usaha.validation.js):
      • Memperbaiki refinement rule skema Zod digit string agar menangani data kosong/nullable tanpa memicu validation error.
      • Mengonfigurasi nib_penerima menjadi optional dan mendukung whitelist karakter 0.
    • Pembersihan Helper Manual Release (app/helpers/kemendag-axios-interceptor.js):
      • Menghapus logika pelepasan manual lock Redis yang redundan pada interceptor axios karena pelepasan lock kini terpusat secara deterministik pada middleware submission_cooldown.js.
  • Perubahan Database (DDL / DML):

    sql
    -- Tidak ada perubahan skema database (DDL/DML) untuk task ini.
    -- Perubahan difokuskan pada middleware rate limiting/lock Redis, integrasi API Kemendag, dan Zod validation schema.
  • Kontrak API & Response Payload:

    • Endpoints Terkait:
      • POST /api/sipt/send
      • POST /api/sipt/pelaku-usaha
      • POST /api/sipt/cancel
    • Perubahan Behavior:
      • Payload dengan properti nib atau nib_penerima bernilai null, "", atau undefined kini diterima valid tanpa menghasilkan runtime error 500.
      • Waktu tunggu retry saat terjadi concurrent submission berkurang menjadi maksimal 1 menit, dan lock Redis dibebaskan seketika setelah request selesai dikembalikan ke client.

4. Bukti Teknis (Technical Proof & Audit Trail)

  • Repository: sipt-backend
  • Branch: development
  • Commit ID / Hash: ebd871dc5d343ae7ef7983e659c8ef773b18c434
  • Merge Request / PR: -

Cuplikan Kode / Implementasi Inti

javascript
// File: app/middlewares/submission_cooldown.js
const COOLDOWN_SECONDS = 60; // 1 menit
export const submissionCooldown = (action) => {
  return async (req, res, next) => {
    try {
      const nomorLayanan = req.nomorLayanan;
      if (!nomorLayanan) return next();
      const cacheKey = CacheKeys.SUBMISSION_COOLDOWN(action, nomorLayanan);
      const result = await redisClient.set(cacheKey, Date.now().toString(), "EX", COOLDOWN_SECONDS, "NX");
      if (result === null) {
        const ttl = await redisClient.ttl(cacheKey);
        const minutesLeft = Math.ceil(ttl / 60);
        throw new TooManyRequestsError(
          `Pengajuan untuk nomor layanan ${nomorLayanan} sudah dikirim. Silahkan coba lagi dalam ${minutesLeft} menit jika status masih ${statusSipt.draft} atau ${statusSipt.gagal_kirim}.`
        );
      }
      let released = false;
      const releaseLock = async () => {
        if (released) return;
        released = true;
        try {
          await redisClient.del(cacheKey);
        } catch (err) {
          logger.error({ err, nomor_layanan: nomorLayanan, action }, "Failed to release submission cooldown lock");
        }
      };
      // Monkey-patching res.end untuk auto-release lock saat request selesai/error
      const originalEnd = res.end;
      res.end = function (...args) {
        releaseLock();
        return originalEnd.apply(this, args);
      };
      next();
    } catch (error) {
      next(error);
    }
  };
};
javascript
// File: app/api/kemendag.api.js (Null-Safety NIB)
ekspedisi: {
  npwp: ekspedisi.npwp,
  nib: ekspedisi.nib?.trim(),
  tipe_perusahaan: ekspedisi.tipe_perusahaan,
  nama: ekspedisi.nama,
  // ...
},
penerima: {
  jenis_tujuan: penerima.jenis_tujuan,
  npwp_penerima: penerima.npwp_penerima,
  nib_penerima: penerima.nib_penerima?.trim(),
  nama_penerima: penerima.nama_penerima,
  // ...
}

5. Bukti Verifikasi Pengujian (QA / Unit Test / API Verification)

A. Verifikasi Unit Test (Development Stage)

  • Test Suite Files:
    • tests/middlewares/submission_cooldown.test.js
    • tests/validations/pelaku_usaha.validation.test.js
  • Status Eksekusi CLI: PASSED (7/7 tests passed)
javascript
// File: tests/middlewares/submission_cooldown.test.js
describe('submissionCooldown middleware', () => {
  it('allows submission when Redis SET NX returns "OK"', async () => {
    mockSet.mockResolvedValueOnce('OK');
    res.end = vi.fn();
    const middleware = submissionCooldown('receivePelaporan');
    await middleware(req, res, next);
    expect(mockSet).toHaveBeenCalledWith(
      expect.stringContaining('cooldown:receivePelaporan:NL-001'),
      expect.any(String),
      'EX',
      60,
      'NX'
    );
    expect(next).toHaveBeenCalled();
  });
});
text
 RUN  v4.1.11 D:/WORK/LNSW/sipt-backend
 ✓ tests/validations/pelaku_usaha.validation.test.js (4 tests) 10ms
 ✓ tests/middlewares/submission_cooldown.test.js (3 tests) 7ms
 Test Files  2 passed (2)
      Tests  7 passed (7)
   Start at  13:33:25
   Duration  848ms (transform 351ms, setup 0ms, import 690ms, tests 18ms, environment 0ms)

B. Verifikasi Integrasi Staging / Production

Diisi saat naik ke Staging atau Production.

json
{
  "status": "PENDING",
  "note": "Menunggu deployment ke environment Staging untuk pengujian end-to-end integrasi Kemendag dan verifikasi release lock Redis."
}
  • Hasil Pengujian UAT: PENDING
  • Catatan QA:

Single Source of Truth (SSOT) Arsitektur & Perubahan Teknis Backend