TorQ Integration Runbook (Sravz)
This document captures the TorQ/KDB work completed in this repo so far, including fixes, runtime commands, SSL work, and websocket feed integration notes.
Environment
- Local compose file:
localhost-docker-compose.yaml - TorQ container name pattern:
sravz-torq-1 - KDB runtime: KDB-X 5.0 (Community)
- TorQ core in container:
/opt/backend-q/deploy/TorQ/latest - TorQ app in container:
/opt/backend-q/deploy/TorQApp/latest
Major Fixes Completed
1) KDB-X .Q.lim[] compatibility bug in TorQ core
Issue:
- TorQ checked connection limit with
0W=.Q.lim[][\conns]`. - In KDB-X CE,
.Q.lim[]returns a dict (cur|...,lim|...) and this comparison failed.
Fix:
- Extract limit scalar from nested dict:
x[\conns][`lim]`.
Files updated:
backend-q/TorQ/config/settings/default.qbackend-q/TorQ/config/settings/segmentedchainedtickerplant.q- Matching app override restored in:
deploy/TorQApp/v1.12.1/TorQ-Finance-Starter-Pack-1.12.1/appconfig/settings/segmentedchainedtickerplant.q
Result:
- Discovery/connection limit logic now behaves correctly under KDB-X CE.
2) Runtime script update for realtime stack
Change:
- Removed discovery process from realtime start helper.
File:
backend-q/docker/torq-realtime.sh
Current realtime helper starts:
stp1 sctp1 feed1 gateway1
3) Install scripts moved under backend-q
Moved:
install_kdb.sh->backend-q/install_kdb.shinstalltorqapp.sh->backend-q/installtorqapp.sh
Adjusted:
backend-q/Dockerfilecopy paths updated accordingly.
4) Finance Starter Pack setenv.sh CA bundle fix
Issue:
- Legacy script downloaded
cacert.pmand exported it as CA bundle. - That caused OpenSSL certificate load errors.
Fix in app script:
- Prefer existing CA bundle from env/system.
- Fallback download uses
https://curl.se/ca/cacert.pem.
File:
backend-q/TorQ-Finance-Starter-Pack/setenv.sh
Important deployment note:
- In container,
/opt/backend-q/deploy/bin/setenv.shmay be a copied stale file. - Local compose now mounts deploy-aware wrapper to that path.
5) Local deploy-aware setenv wrapper
Added:
backend-q/docker/setenv-deploy.sh
Purpose:
- Enforces deploy path variables (
TORQHOME,KDBAPPCODE, etc.) - Creates log directory safely
- Applies corrected CA bundle behavior
Mounted by local compose:
localhost-docker-compose.yaml
6) Local TLS file preparation for q websocket client
Added:
backend-q/docker/prepare_q_tls.sh
Purpose:
- Splits cert bundle into:
server-key.pemserver-crt.pemcacert.pem
Added Make target:
make -C backend-q prep-tls
Local compose mounts these to:
/usr/lib/ssl/server-key.pem/usr/lib/ssl/server-crt.pem/usr/lib/ssl/cacert.pem
7) Websocket feed implementation
Primary file:
backend-q/TorQ-Finance-Starter-Pack/code/tick/feed_ws.q
Capabilities now:
- Uses q websocket client handshake API (not
hopenws shortcut) - Works with two sockets in one process:
- trades:
/ws/us - quotes:
/ws/us-quote
- trades:
- Handle-based routing via
.z.w - Subscribes after per-socket
200 Authorized - Publishes to TorQ tables:
tradequote
- Publishes side-channel raw table for provider timestamp preservation:
eodwsraw
Schema update:
- Added
eodwsrawinbackend-q/TorQ-Finance-Starter-Pack/database.q
Side-Channel Table
Added table:
eodwsraw
Goal:
- Keep provider timestamp (
t) exactly, alongside normalized fields and raw payload text.
Fields:
time(ingest timestamp)providerts(converted from provider epoch ms)symkind(trade/quote)price,bid,ask,size,bsize,asizerawsrc
Commands
Build / run local torq service
From repo root:
docker compose -f localhost-docker-compose.yaml up -d torq
Prepare local TLS files
make -C backend-q prep-tls
TorQ process summary
make summary-backend-q
Enter torq container shell
docker exec -it sravz-torq-1 bash
Start websocket feed process manually
Inside container:
source /opt/backend-q/deploy/bin/setenv.sh
q "$TORQHOME/torq.q" -proctype feed -procname feed_ws1 -p 6098 -debug -noredirect -trap -load "$KDBAPPCODE/tick/feed_ws.q"
Known good direct handshake probe (inside container)
.z.ws:{0N!"ws msg";0N!x;}
req:"GET /ws/us?api_token=demo HTTP/1.1\r\nHost: ws.eodhistoricaldata.com:443\r\n\r\n"
res:.[{[u;r] u r};(`$":wss://ws.eodhistoricaldata.com:443";req);{[e] e}]
show type res
show res
Common Troubleshooting Notes
/torq.q. OS reports: No such file or directory
Cause:
TORQHOMEunset in shell.
Fix:
- source setenv, or use absolute path.
connection failed: type / websocket open issues
Cause:
- Wrong argument type or connection form.
Fix:
- Use q websocket handshake API:
(`$":wss://host:443") "GET ..."
X509_load_cert_crl_file_ex:no certificate or crl found
Cause:
- Invalid CA file path/content (historically from
cacert.pm).
Fix:
- Ensure
SSL_CA_CERT_FILEpoints to a real PEM bundle. - Use corrected deploy setenv and mounted CA bundle.
TorQ logger type failures
Cause:
- Passing list/mixed types instead of single char vector in
.lg.*message.
Fix:
- Flatten log text before
.lg.o/.lg.ecalls.
onmsg failed: rank
Cause:
- Trap function arity mismatch in
.[f;args;e].
Fix:
- Ensure
flambda arg list matches passed args exactly.
EOD subscribe validation errors
Observed:
Action and symbols should be string
Fix:
- Send:
{"action":"subscribe","symbols":"AMZN,TSLA"}
Quote endpoint payload shape
Confirmed /ws/us-quote payload keys:
s,ap,as,bp,bs,t
Current quote mapper supports these aliases and common alternates.
Scaling Guidance (600 tickers)
Provider constraint:
- 50 tickers per websocket connection.
Recommendation:
- Minimum 12 connections for 600 symbols.
- Prefer 14-16 connections for headroom and rebalance.
- Shard symbols deterministically across sockets.
- Run multiple feed processes (not one giant process) for isolation.
For a full feed handler design, see:
docs-hugo/content/docs/Tech/kdb/feed_handler.md
