
Table of Contents
-
About The Project
-
Getting Started
- Usage
- Roadmap
- Contributing
- License
- Contact
- Acknowledgments
About The Project

DIS Reader is a Go service that exposes DIS (AS/400) data to other applications with a stable, API-first contract. It runs in two modes:
- Embedded mode (default): ships the JDBC runner inside the binary and serves queries directly to the DIS host you configure.
- Remote agent mode: a lightweight LAN agent runs the JDBC bridge next to your DIS server and proxies requests to the cloud over gRPC—no inbound ports required.
Capabilities:
- Typed services for units, invoices, and parts with filter/sort/paging helpers.
- Health-checked lifecycle around the JDBC runner (start, connect, ping, shutdown).
- Debug Search batch runner that emits SQLite or CSV datasets for downstream tooling.
- Simple config surface via
disreader.yaml or DISREADER_* environment variables.
(back to top)
Built With
(back to top)
Getting Started
Choose embedded when you can reach DIS directly; choose remote when DIS lives behind firewalls and only outbound traffic is allowed.
Prerequisites
- Go 1.24+
- Java 11+ on PATH (for embedded JDBC runner or agent)
protoc, protoc-gen-go, protoc-gen-go-grpc (only if you regenerate bridge stubs)
- (Remote mode) TLS egress to the bridge server
Installation
- Clone the repo
git clone https://github.com/BeardedWonderDev/DIS-Reader.git
cd DIS-Reader
- (Optional) Regenerate gRPC stubs
protoc --go_out=. --go-grpc_out=. proto/bridge.proto
- Build binaries
go build ./cmd/... # core service binaries
go build ./cmd/agent/... # remote agent daemon
(back to top)
Usage
Embedded mode (default)
Start the service using your DIS host credentials:
DISREADER_DISCONFIG_HOST=10.0.0.5 DISREADER_DISCONFIG_USER=XXXXX DISREADER_DISCONFIG_PASSWORD=XXXXX go run ./...
- Config file:
disreader.yaml
- Key settings:
disConfig.host|user|password, JDBC javaPath/jdbcPort, connection pool sizes.
- Consumers call the exported Go services (or any gRPC/HTTP gateway you layer on) to fetch units, invoices, and parts.
Remote mode (agent bridge)
- Run the LAN agent near DIS (one per tenant, or more for HA):
./cmd/agent/agent --config agent.yaml
- Client construction (Go):
remote, err := disreader.NewDISReaderRemote(cfg, logger).
WithDefaultTenant("tenant-1"). // optional; omit for pure per-call tenancy
Build()
rows, _ := remote.UnitService("tenant-1").ListUnits(ctx, lp)
Multi-tenant: set one agent per tenant; call tenant-aware methods (Connect(ctx, tenant), UnitService(tenant)). Do not rely on a default tenant from config; supply it via WithDefaultTenant or per call.
Remote client (full example):
ctx := context.Background()
remote, err := disreader.NewDISReaderRemote(cfg, logger).
WithDefaultTenant("tenant-a").
Build()
if err != nil { log.Fatal(err) }
if err := remote.PingBridge(ctx); err != nil { log.Fatal(err) }
if err := remote.PingAgent(ctx, "tenant-a"); err != nil { log.Fatal(err) }
if err := remote.Connect(ctx, "tenant-a"); err != nil { log.Fatal(err) }
unitSvc := remote.UnitService("tenant-a")
units, err := unitSvc.ListUnits(ctx, types.ListParams{Limit: 10})
if err != nil { log.Fatal(err) }
fmt.Println("units", len(units))
// Start/stop the remote JDBC runner on the agent (mirrors embedded lifecycle)
if err := remote.StartJDBCRunner(ctx, "tenant-a"); err != nil { log.Fatal(err) }
defer remote.StopJDBCRunner(ctx, "tenant-a")
// Read the agent's current config (sanitized: secrets are write-only)
cfgStatus, err := remote.ReadAgentConfig(ctx, "tenant-a")
if err != nil { log.Fatal(err) }
fmt.Println("agent host:", cfgStatus.GetRuntime().GetDisHost(), "has password?", cfgStatus.GetRuntime().GetHasPassword())
Defaults and ports:
- The remote builder auto-starts gRPC (/AgentService) on
:8443 and HTTP (/healthz,/metrics, pprof if enabled) on :8080. Override with env DISREADER_BRIDGE_PORT and DISREADER_BRIDGE_HTTP_PORT, or supply your own servers via WithGRPC/WithMux.
Bridge config keys:
bridge.mode: embedded|remote (default embedded)
bridge.serverURL, bridge.clientID, bridge.clientSecret
- TLS:
bridge.tls.insecure, bridge.tls.caFile
Debug Search Output Modes
Produce ad-hoc datasets for analysis:
- Default SQLite:
debug-search.db
- CSV: set
debugSearch.defaultOutputMode: csv or DISREADER_DEBUGSEARCH_DEFAULTOUTPUTMODE=csv
- Path override:
debugSearch.defaultOutputPath / DISREADER_DEBUGSEARCH_DEFAULTOUTPUTPATH
Control plane (TUI + GUI)
You can manage the remote agent without CLI flags by using the bundled control surfaces. Both talk to the local control API exposed by the agent.
- Enable the control API in
agent.yaml (or env):
control:
enabled: true
addr: "127.0.0.1:7777"
token: "set-a-strong-token"
Start/restart the agent so it listens on the control API.
- TUI (
agentctl):
- Download the
agentctl binary from the release matching your OS/arch.
- Run
./agentctl --addr http://127.0.0.1:7777 --token <token>.
- Use the form to set
serverURL, clientID/Secret, DIS host creds, JDBC port/java path, TLS flags, then “Save & Apply”.
- Use the buttons to
Install, Start, Stop, Restart, and view status.
- GUI (
dis-agent-gui):
- Download the GUI binary for your platform and run it (macOS app, Windows exe, or Linux binary with GTK/WebKit deps).
- Point it at the control API address/token.
- Fill out config fields and “Save + Install + Start” for first-run; “Save + Restart” for updates.
- The dashboard shows bridge status, last heartbeat, and raw status. Auto-refresh can be enabled in the UI.
(back to top)
Roadmap
TODO: replace with the post–remote-agent roadmap once the current phase completes.
(back to top)
Contributing
Please run go test ./... and go vet ./... before opening a PR. Add regression tests for service changes and include sample configs for new bridge/agent settings.
(back to top)
License
Distributed under the project_license. See LICENSE.txt for more information.
(back to top)
DIS Reader Team - maintainer@example.com
Project Link: https://github.com/BeardedWonderDev/DIS-Reader
(back to top)
Acknowledgments
- IBM i / AS/400 community resources
- gRPC & Protocol Buffers maintainers
- SQLite project
- JT400 / JDBC bridge contributors
(back to top)