mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-15 20:05:13 +02:00
**refactor(dynamic): add HTTP emulators for Pubsub, Rabbit, and NATS with publish/deliver/ack logic, extend event recording, endpoint rewriting, and SDK compatibility across Java, Go, Python, and Rust**
This commit is contained in:
parent
57d3677bd4
commit
a55849f1ca
7 changed files with 729 additions and 65 deletions
|
|
@ -2160,15 +2160,31 @@ fn emit_message_handler_harness(spec: &HarnessSpec, queue: &str) -> HarnessSourc
|
|||
crate::dynamic::stubs::nats_source(crate::symbol::Lang::Go),
|
||||
crate::dynamic::stubs::NATS_PUBLISH_MARKER,
|
||||
format!(
|
||||
r##" broker := NewNyxNatsLoopback()
|
||||
broker.Subscribe("{queue}", func(msg *NyxNatsMsg) {{
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "deliver", "{queue}", string(msg.Data))
|
||||
nyxDispatch(msg)
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "ack", "{queue}", msg.Subject)
|
||||
}})
|
||||
fmt.Println("{publish_marker} " + "{queue}")
|
||||
nyxRecordBrokerPublish("NYX_NATS_LOG", "{queue}", payload)
|
||||
broker.Publish("{queue}", payload)"##,
|
||||
r##" if msg, ok := nyxFetchHttpBroker("NYX_NATS_ENDPOINT", "subjects", "{queue}", payload, "{publish_marker}"); ok {{
|
||||
data := msg["data"]
|
||||
natsMsg := &NyxNatsMsg{{Subject: msg["subject"], Data: []byte(data), Reply: msg["reply"]}}
|
||||
if natsMsg.Subject == "" {{
|
||||
natsMsg.Subject = "{queue}"
|
||||
}}
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "deliver", "{queue}", data)
|
||||
nyxDispatch(natsMsg)
|
||||
ackID := msg["ack_id"]
|
||||
if ackID == "" {{
|
||||
ackID = natsMsg.Subject
|
||||
}}
|
||||
nyxAckHttpBroker("NYX_NATS_ENDPOINT", "subjects", "{queue}", ackID)
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "ack", "{queue}", ackID)
|
||||
}} else {{
|
||||
broker := NewNyxNatsLoopback()
|
||||
broker.Subscribe("{queue}", func(msg *NyxNatsMsg) {{
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "deliver", "{queue}", string(msg.Data))
|
||||
nyxDispatch(msg)
|
||||
nyxRecordBrokerEvent("NYX_NATS_LOG", "ack", "{queue}", msg.Subject)
|
||||
}})
|
||||
fmt.Println("{publish_marker} " + "{queue}")
|
||||
nyxRecordBrokerPublish("NYX_NATS_LOG", "{queue}", payload)
|
||||
broker.Publish("{queue}", payload)
|
||||
}}"##,
|
||||
queue = queue,
|
||||
publish_marker = crate::dynamic::stubs::NATS_PUBLISH_MARKER,
|
||||
),
|
||||
|
|
@ -2177,16 +2193,33 @@ fn emit_message_handler_harness(spec: &HarnessSpec, queue: &str) -> HarnessSourc
|
|||
crate::dynamic::stubs::pubsub_source(crate::symbol::Lang::Go),
|
||||
crate::dynamic::stubs::PUBSUB_PUBLISH_MARKER,
|
||||
format!(
|
||||
r##" broker := NewNyxPubsubLoopback()
|
||||
broker.Subscribe("{queue}", func(msg *NyxPubsubMessage) {{
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "deliver", "{queue}", string(msg.Data))
|
||||
nyxDispatch(msg)
|
||||
msg.Ack()
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "ack", "{queue}", msg.ID)
|
||||
}})
|
||||
fmt.Println("{publish_marker} " + "{queue}")
|
||||
nyxRecordBrokerPublish("NYX_PUBSUB_LOG", "{queue}", payload)
|
||||
broker.Publish("{queue}", payload)"##,
|
||||
r##" if msg, ok := nyxFetchHttpBroker("NYX_PUBSUB_ENDPOINT", "topics", "{queue}", payload, "{publish_marker}"); ok {{
|
||||
data := msg["data"]
|
||||
pubsubMsg := &NyxPubsubMessage{{ID: msg["id"], Data: []byte(data)}}
|
||||
if pubsubMsg.ID == "" {{
|
||||
pubsubMsg.ID = msg["ack_id"]
|
||||
}}
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "deliver", "{queue}", data)
|
||||
nyxDispatch(pubsubMsg)
|
||||
pubsubMsg.Ack()
|
||||
ackID := msg["ack_id"]
|
||||
if ackID == "" {{
|
||||
ackID = pubsubMsg.ID
|
||||
}}
|
||||
nyxAckHttpBroker("NYX_PUBSUB_ENDPOINT", "topics", "{queue}", ackID)
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "ack", "{queue}", ackID)
|
||||
}} else {{
|
||||
broker := NewNyxPubsubLoopback()
|
||||
broker.Subscribe("{queue}", func(msg *NyxPubsubMessage) {{
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "deliver", "{queue}", string(msg.Data))
|
||||
nyxDispatch(msg)
|
||||
msg.Ack()
|
||||
nyxRecordBrokerEvent("NYX_PUBSUB_LOG", "ack", "{queue}", msg.ID)
|
||||
}})
|
||||
fmt.Println("{publish_marker} " + "{queue}")
|
||||
nyxRecordBrokerPublish("NYX_PUBSUB_LOG", "{queue}", payload)
|
||||
broker.Publish("{queue}", payload)
|
||||
}}"##,
|
||||
queue = queue,
|
||||
publish_marker = crate::dynamic::stubs::PUBSUB_PUBLISH_MARKER,
|
||||
),
|
||||
|
|
@ -2238,6 +2271,9 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"reflect"
|
||||
|
|
@ -2289,6 +2325,77 @@ func nyxRecordBrokerPublish(envName string, destination string, payload string)
|
|||
nyxRecordBrokerEvent(envName, "publish", destination, payload)
|
||||
}}
|
||||
|
||||
func nyxFetchHttpBroker(envName string, root string, destination string, payload string, marker string) (map[string]string, bool) {{
|
||||
endpoint := os.Getenv(envName)
|
||||
if !(strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://")) {{
|
||||
return nil, false
|
||||
}}
|
||||
client := http.Client{{Timeout: 2 * time.Second}}
|
||||
base := strings.TrimRight(endpoint, "/")
|
||||
escaped := url.PathEscape(destination)
|
||||
fmt.Println(marker + " " + destination)
|
||||
postReq, err := http.NewRequest(
|
||||
"POST",
|
||||
base+"/"+root+"/"+escaped+"/messages",
|
||||
strings.NewReader(payload),
|
||||
)
|
||||
if err != nil {{
|
||||
return nil, false
|
||||
}}
|
||||
postResp, err := client.Do(postReq)
|
||||
if err != nil {{
|
||||
fmt.Fprintf(os.Stderr, "NYX_BROKER_HTTP_FALLBACK: %v\n", err)
|
||||
return nil, false
|
||||
}}
|
||||
_, _ = io.Copy(io.Discard, postResp.Body)
|
||||
_ = postResp.Body.Close()
|
||||
if postResp.StatusCode >= 400 {{
|
||||
return nil, false
|
||||
}}
|
||||
getResp, err := client.Get(base + "/" + root + "/" + escaped + "/messages?max=1")
|
||||
if err != nil {{
|
||||
fmt.Fprintf(os.Stderr, "NYX_BROKER_HTTP_FALLBACK: %v\n", err)
|
||||
return nil, false
|
||||
}}
|
||||
defer getResp.Body.Close()
|
||||
if getResp.StatusCode >= 400 {{
|
||||
return nil, false
|
||||
}}
|
||||
raw, err := io.ReadAll(getResp.Body)
|
||||
if err != nil {{
|
||||
return nil, false
|
||||
}}
|
||||
var envelope struct {{
|
||||
Messages []map[string]string `json:"messages"`
|
||||
}}
|
||||
if err := json.Unmarshal(raw, &envelope); err != nil || len(envelope.Messages) == 0 {{
|
||||
return nil, false
|
||||
}}
|
||||
return envelope.Messages[0], true
|
||||
}}
|
||||
|
||||
func nyxAckHttpBroker(envName string, root string, destination string, ackID string) {{
|
||||
endpoint := os.Getenv(envName)
|
||||
if !(strings.HasPrefix(endpoint, "http://") || strings.HasPrefix(endpoint, "https://")) {{
|
||||
return
|
||||
}}
|
||||
client := http.Client{{Timeout: 2 * time.Second}}
|
||||
base := strings.TrimRight(endpoint, "/")
|
||||
escaped := url.PathEscape(destination)
|
||||
values := url.Values{{}}
|
||||
values.Set("ack_id", ackID)
|
||||
resp, err := client.Post(
|
||||
base+"/"+root+"/"+escaped+"/ack",
|
||||
"application/x-www-form-urlencoded",
|
||||
strings.NewReader(values.Encode()),
|
||||
)
|
||||
if err != nil {{
|
||||
return
|
||||
}}
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
}}
|
||||
|
||||
func main() {{
|
||||
__nyx_install_crash_guard("{handler}")
|
||||
payload := nyxPayload()
|
||||
|
|
|
|||
|
|
@ -3834,37 +3834,39 @@ fn emit_message_handler_harness(
|
|||
JavaBroker::Rabbit => (
|
||||
crate::dynamic::stubs::RABBIT_PUBLISH_MARKER,
|
||||
format!(
|
||||
r#" NyxRabbitChannel chan = new NyxRabbitChannel();
|
||||
chan.basicConsume({queue:?}, (mid, body) -> {{
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "deliver", {queue:?}, body);
|
||||
System.out.println("__NYX_SINK_HIT__");
|
||||
boolean success = false;
|
||||
try {{
|
||||
java.lang.reflect.Method m = entryInst.getClass().getDeclaredMethod({handler:?}, String.class, String.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(entryInst, mid, body);
|
||||
success = true;
|
||||
}} catch (NoSuchMethodException nsme) {{
|
||||
r#" if (!nyxTryRabbitHttp({queue:?}, payload, entryInst, {handler:?})) {{
|
||||
NyxRabbitChannel chan = new NyxRabbitChannel();
|
||||
chan.basicConsume({queue:?}, (mid, body) -> {{
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "deliver", {queue:?}, body);
|
||||
System.out.println("__NYX_SINK_HIT__");
|
||||
boolean success = false;
|
||||
try {{
|
||||
java.lang.reflect.Method m2 = entryInst.getClass().getDeclaredMethod({handler:?}, String.class);
|
||||
m2.setAccessible(true);
|
||||
m2.invoke(entryInst, body);
|
||||
java.lang.reflect.Method m = entryInst.getClass().getDeclaredMethod({handler:?}, String.class, String.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(entryInst, mid, body);
|
||||
success = true;
|
||||
}} catch (Exception ie) {{
|
||||
Throwable c = (ie instanceof java.lang.reflect.InvocationTargetException && ie.getCause() != null) ? ie.getCause() : ie;
|
||||
}} catch (NoSuchMethodException nsme) {{
|
||||
try {{
|
||||
java.lang.reflect.Method m2 = entryInst.getClass().getDeclaredMethod({handler:?}, String.class);
|
||||
m2.setAccessible(true);
|
||||
m2.invoke(entryInst, body);
|
||||
success = true;
|
||||
}} catch (Exception ie) {{
|
||||
Throwable c = (ie instanceof java.lang.reflect.InvocationTargetException && ie.getCause() != null) ? ie.getCause() : ie;
|
||||
System.err.println("NYX_EXCEPTION: " + c.getClass().getName() + ": " + c.getMessage());
|
||||
}}
|
||||
}} catch (Exception e) {{
|
||||
Throwable c = (e instanceof java.lang.reflect.InvocationTargetException && e.getCause() != null) ? e.getCause() : e;
|
||||
System.err.println("NYX_EXCEPTION: " + c.getClass().getName() + ": " + c.getMessage());
|
||||
}}
|
||||
}} catch (Exception e) {{
|
||||
Throwable c = (e instanceof java.lang.reflect.InvocationTargetException && e.getCause() != null) ? e.getCause() : e;
|
||||
System.err.println("NYX_EXCEPTION: " + c.getClass().getName() + ": " + c.getMessage());
|
||||
}}
|
||||
if (success) {{
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "ack", {queue:?}, mid);
|
||||
}}
|
||||
}});
|
||||
System.out.println({publish_marker:?} + " " + {queue:?});
|
||||
nyxRecordBrokerPublish("NYX_RABBIT_LOG", {queue:?}, payload);
|
||||
chan.basicPublish("", {queue:?}, payload);"#,
|
||||
if (success) {{
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "ack", {queue:?}, mid);
|
||||
}}
|
||||
}});
|
||||
System.out.println({publish_marker:?} + " " + {queue:?});
|
||||
nyxRecordBrokerPublish("NYX_RABBIT_LOG", {queue:?}, payload);
|
||||
chan.basicPublish("", {queue:?}, payload);
|
||||
}}"#,
|
||||
handler = handler,
|
||||
queue = queue,
|
||||
publish_marker = crate::dynamic::stubs::RABBIT_PUBLISH_MARKER,
|
||||
|
|
@ -3984,6 +3986,71 @@ public class NyxHarness {{
|
|||
}}
|
||||
}}
|
||||
|
||||
static boolean nyxTryRabbitHttp(String queue, String payload, Object entryInst, String handler) {{
|
||||
String endpoint = System.getenv("NYX_RABBIT_ENDPOINT");
|
||||
if (endpoint == null || !(endpoint.startsWith("http://") || endpoint.startsWith("https://"))) {{
|
||||
return false;
|
||||
}}
|
||||
try {{
|
||||
String base = endpoint.replaceAll("/+$", "");
|
||||
String queuePath = java.net.URLEncoder.encode(queue, java.nio.charset.StandardCharsets.UTF_8);
|
||||
System.out.println({rabbit_publish_marker:?} + " " + queue);
|
||||
nyxHttpRequest(
|
||||
"POST",
|
||||
base + "/queues/" + queuePath + "/messages",
|
||||
payload.getBytes(java.nio.charset.StandardCharsets.UTF_8)
|
||||
);
|
||||
String messagesJson = nyxHttpRequest(
|
||||
"GET",
|
||||
base + "/queues/" + queuePath + "/messages?max=1",
|
||||
new byte[0]
|
||||
);
|
||||
if (messagesJson == null || !messagesJson.contains("\"messages\"") || !messagesJson.contains("\"body\"")) {{
|
||||
return false;
|
||||
}}
|
||||
String body = nyxJsonStringField(messagesJson, "body");
|
||||
String tag = nyxJsonStringField(messagesJson, "delivery_tag");
|
||||
if (tag == null || tag.isEmpty()) {{
|
||||
tag = nyxJsonStringField(messagesJson, "ack_id");
|
||||
}}
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "deliver", queue, body);
|
||||
System.out.println("__NYX_SINK_HIT__");
|
||||
boolean success = false;
|
||||
try {{
|
||||
java.lang.reflect.Method m = entryInst.getClass().getDeclaredMethod(handler, String.class, String.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(entryInst, tag, body);
|
||||
success = true;
|
||||
}} catch (NoSuchMethodException nsme) {{
|
||||
try {{
|
||||
java.lang.reflect.Method m2 = entryInst.getClass().getDeclaredMethod(handler, String.class);
|
||||
m2.setAccessible(true);
|
||||
m2.invoke(entryInst, body);
|
||||
success = true;
|
||||
}} catch (Exception ie) {{
|
||||
Throwable c = (ie instanceof java.lang.reflect.InvocationTargetException && ie.getCause() != null) ? ie.getCause() : ie;
|
||||
System.err.println("NYX_EXCEPTION: " + c.getClass().getName() + ": " + c.getMessage());
|
||||
}}
|
||||
}} catch (Exception e) {{
|
||||
Throwable c = (e instanceof java.lang.reflect.InvocationTargetException && e.getCause() != null) ? e.getCause() : e;
|
||||
System.err.println("NYX_EXCEPTION: " + c.getClass().getName() + ": " + c.getMessage());
|
||||
}}
|
||||
if (success) {{
|
||||
String ackBody = "ack_id=" + java.net.URLEncoder.encode(tag == null ? "" : tag, java.nio.charset.StandardCharsets.UTF_8);
|
||||
nyxHttpRequest(
|
||||
"POST",
|
||||
base + "/queues/" + queuePath + "/ack",
|
||||
ackBody.getBytes(java.nio.charset.StandardCharsets.UTF_8)
|
||||
);
|
||||
nyxRecordBrokerEvent("NYX_RABBIT_LOG", "ack", queue, tag == null ? "" : tag);
|
||||
}}
|
||||
return true;
|
||||
}} catch (Throwable e) {{
|
||||
System.err.println("NYX_RABBIT_HTTP_FALLBACK: " + e.getClass().getName() + ": " + e.getMessage());
|
||||
return false;
|
||||
}}
|
||||
}}
|
||||
|
||||
static boolean nyxTryRealKafkaClient(String topic, String payload, Object entryInst, String handler) {{
|
||||
Object consumer = null;
|
||||
try {{
|
||||
|
|
@ -4257,6 +4324,7 @@ public class NyxHarness {{
|
|||
entry_class = entry_class,
|
||||
dispatch_block = dispatch_block,
|
||||
kafka_publish_marker = crate::dynamic::stubs::KAFKA_PUBLISH_MARKER,
|
||||
rabbit_publish_marker = crate::dynamic::stubs::RABBIT_PUBLISH_MARKER,
|
||||
sqs_publish_marker = crate::dynamic::stubs::SQS_PUBLISH_MARKER,
|
||||
);
|
||||
HarnessSource {
|
||||
|
|
|
|||
|
|
@ -980,8 +980,7 @@ fn emit_message_handler(spec: &HarnessSpec, queue: &str) -> HarnessSource {
|
|||
publish_marker = crate::dynamic::stubs::SQS_PUBLISH_MARKER,
|
||||
),
|
||||
PythonBroker::Pubsub => format!(
|
||||
r#"_loop = NyxPubsubLoopback()
|
||||
def _nyx_pubsub_dispatch(message):
|
||||
r#"def _nyx_pubsub_dispatch(message):
|
||||
_h = getattr(_entry_mod, {handler:?}, None)
|
||||
if _h is None:
|
||||
print("NYX_HANDLER_NOT_FOUND: " + {handler:?}, file=sys.stderr, flush=True)
|
||||
|
|
@ -991,17 +990,18 @@ def _nyx_pubsub_dispatch(message):
|
|||
if hasattr(message, "ack"):
|
||||
message.ack()
|
||||
_nyx_record_broker_event("NYX_PUBSUB_LOG", "ack", {queue:?}, getattr(message, "message_id", ""))
|
||||
_loop.subscribe({queue:?}, _nyx_pubsub_dispatch)
|
||||
print({publish_marker:?} + " " + {queue:?}, flush=True)
|
||||
_nyx_record_broker_publish("NYX_PUBSUB_LOG", {queue:?}, payload)
|
||||
_loop.publish({queue:?}, payload)"#,
|
||||
if not _nyx_try_pubsub_http({queue:?}, payload, _nyx_pubsub_dispatch):
|
||||
_loop = NyxPubsubLoopback()
|
||||
_loop.subscribe({queue:?}, _nyx_pubsub_dispatch)
|
||||
print({publish_marker:?} + " " + {queue:?}, flush=True)
|
||||
_nyx_record_broker_publish("NYX_PUBSUB_LOG", {queue:?}, payload)
|
||||
_loop.publish({queue:?}, payload)"#,
|
||||
handler = handler,
|
||||
queue = queue,
|
||||
publish_marker = crate::dynamic::stubs::PUBSUB_PUBLISH_MARKER,
|
||||
),
|
||||
PythonBroker::Rabbit => format!(
|
||||
r#"_chan = NyxRabbitChannel()
|
||||
def _nyx_rabbit_dispatch(ch, method, props, body):
|
||||
r#"def _nyx_rabbit_dispatch(ch, method, props, body):
|
||||
_h = getattr(_entry_mod, {handler:?}, None)
|
||||
if _h is None:
|
||||
print("NYX_HANDLER_NOT_FOUND: " + {handler:?}, file=sys.stderr, flush=True)
|
||||
|
|
@ -1009,10 +1009,12 @@ def _nyx_rabbit_dispatch(ch, method, props, body):
|
|||
_nyx_record_broker_event("NYX_RABBIT_LOG", "deliver", {queue:?}, body)
|
||||
_h(ch, method, props, body)
|
||||
_nyx_record_broker_event("NYX_RABBIT_LOG", "ack", {queue:?}, getattr(method, "delivery_tag", ""))
|
||||
_chan.basic_consume(queue={queue:?}, on_message_callback=_nyx_rabbit_dispatch)
|
||||
print({publish_marker:?} + " " + {queue:?}, flush=True)
|
||||
_nyx_record_broker_publish("NYX_RABBIT_LOG", {queue:?}, payload)
|
||||
_chan.basic_publish(exchange="", routing_key={queue:?}, body=payload)"#,
|
||||
if not _nyx_try_rabbit_http({queue:?}, payload, _nyx_rabbit_dispatch):
|
||||
_chan = NyxRabbitChannel()
|
||||
_chan.basic_consume(queue={queue:?}, on_message_callback=_nyx_rabbit_dispatch)
|
||||
print({publish_marker:?} + " " + {queue:?}, flush=True)
|
||||
_nyx_record_broker_publish("NYX_RABBIT_LOG", {queue:?}, payload)
|
||||
_chan.basic_publish(exchange="", routing_key={queue:?}, body=payload)"#,
|
||||
handler = handler,
|
||||
queue = queue,
|
||||
publish_marker = crate::dynamic::stubs::RABBIT_PUBLISH_MARKER,
|
||||
|
|
@ -1109,6 +1111,96 @@ def _nyx_try_kafka_http(topic, body, handler_name):
|
|||
print(f"NYX_KAFKA_HTTP_FALLBACK: {{type(_e).__name__}}: {{_e}}", file=sys.stderr, flush=True)
|
||||
return False
|
||||
|
||||
def _nyx_broker_http_roundtrip(env_name, root, destination, body, marker):
|
||||
endpoint = os.environ.get(env_name, "")
|
||||
if not (endpoint.startswith("http://") or endpoint.startswith("https://")):
|
||||
return None
|
||||
try:
|
||||
import json
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
base = endpoint.rstrip("/")
|
||||
dest_path = urllib.parse.quote(str(destination), safe="")
|
||||
print(marker + " " + str(destination), flush=True)
|
||||
_send = urllib.request.Request(
|
||||
base + "/" + root + "/" + dest_path + "/messages",
|
||||
data=str(body).encode("utf-8"),
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(_send, timeout=2).read()
|
||||
_raw = urllib.request.urlopen(
|
||||
base + "/" + root + "/" + dest_path + "/messages?max=1",
|
||||
timeout=2,
|
||||
).read()
|
||||
return json.loads(_raw.decode("utf-8") or "{{}}").get("messages", [])
|
||||
except SystemExit:
|
||||
raise
|
||||
except Exception as _e:
|
||||
print(f"NYX_BROKER_HTTP_FALLBACK: {{type(_e).__name__}}: {{_e}}", file=sys.stderr, flush=True)
|
||||
return None
|
||||
|
||||
def _nyx_broker_http_ack(env_name, root, destination, ack_id):
|
||||
endpoint = os.environ.get(env_name, "")
|
||||
if not (endpoint.startswith("http://") or endpoint.startswith("https://")):
|
||||
return
|
||||
try:
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
base = endpoint.rstrip("/")
|
||||
dest_path = urllib.parse.quote(str(destination), safe="")
|
||||
body = urllib.parse.urlencode({{"ack_id": str(ack_id)}}).encode("utf-8")
|
||||
_ack = urllib.request.Request(
|
||||
base + "/" + root + "/" + dest_path + "/ack",
|
||||
data=body,
|
||||
method="POST",
|
||||
)
|
||||
urllib.request.urlopen(_ack, timeout=2).read()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _nyx_try_pubsub_http(topic, body, dispatcher):
|
||||
messages = _nyx_broker_http_roundtrip(
|
||||
"NYX_PUBSUB_ENDPOINT",
|
||||
"topics",
|
||||
topic,
|
||||
body,
|
||||
{pubsub_publish_marker:?},
|
||||
)
|
||||
if not messages:
|
||||
return False
|
||||
for _msg in messages:
|
||||
_data = _msg.get("data", "")
|
||||
_mid = _msg.get("id", "") or _msg.get("ack_id", "")
|
||||
dispatcher(NyxPubsubMessage(_mid or "nyx-http", _data))
|
||||
_nyx_broker_http_ack(
|
||||
"NYX_PUBSUB_ENDPOINT",
|
||||
"topics",
|
||||
topic,
|
||||
_msg.get("ack_id", _mid),
|
||||
)
|
||||
return True
|
||||
|
||||
def _nyx_try_rabbit_http(queue, body, dispatcher):
|
||||
messages = _nyx_broker_http_roundtrip(
|
||||
"NYX_RABBIT_ENDPOINT",
|
||||
"queues",
|
||||
queue,
|
||||
body,
|
||||
{rabbit_publish_marker:?},
|
||||
)
|
||||
if not messages:
|
||||
return False
|
||||
_chan = NyxRabbitChannel()
|
||||
for _msg in messages:
|
||||
_tag = _msg.get("delivery_tag", "") or _msg.get("ack_id", "")
|
||||
_body = _msg.get("body", "")
|
||||
_method = NyxRabbitMethod(_tag or "nyx-http", queue)
|
||||
_props = NyxRabbitProperties(_tag or "nyx-http")
|
||||
_body_bytes = _body if isinstance(_body, (bytes, bytearray)) else str(_body).encode("utf-8", "replace")
|
||||
dispatcher(_chan, _method, _props, _body_bytes)
|
||||
_nyx_broker_http_ack("NYX_RABBIT_ENDPOINT", "queues", queue, _tag)
|
||||
return True
|
||||
|
||||
def _nyx_try_real_sqs(queue, body, handler_name):
|
||||
endpoint = os.environ.get("NYX_SQS_ENDPOINT", "")
|
||||
if not (endpoint.startswith("http://") or endpoint.startswith("https://")):
|
||||
|
|
@ -1178,6 +1270,8 @@ except Exception as _e:
|
|||
register_and_publish = indent_lines(®ister_and_publish, " "),
|
||||
kafka_publish_marker = crate::dynamic::stubs::KAFKA_PUBLISH_MARKER,
|
||||
sqs_publish_marker = crate::dynamic::stubs::SQS_PUBLISH_MARKER,
|
||||
pubsub_publish_marker = crate::dynamic::stubs::PUBSUB_PUBLISH_MARKER,
|
||||
rabbit_publish_marker = crate::dynamic::stubs::RABBIT_PUBLISH_MARKER,
|
||||
);
|
||||
HarnessSource {
|
||||
source: format!("{preamble}\n{body}\n{postamble}"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue