1pub mod config;
10mod library;
11pub mod metadata;
12mod metrics;
13mod session;
14pub mod sink;
15pub mod source;
16mod worker;
17
18pub use sink::IbmMqSink;
19pub use source::IbmMqSource;
20
21use std::sync::Arc;
22
23use arrow_schema::Schema;
24
25use crate::config::{ConfigKeySpec, ConnectorInfo};
26use crate::registry::ConnectorRegistry;
27
28pub fn register_ibmmq_source(
34 registry: &ConnectorRegistry,
35) -> Result<(), crate::error::ConnectorError> {
36 let info = ConnectorInfo {
37 schema_capabilities: crate::schema::resolution::SchemaCapabilities {
38 built_in_formats: vec![
39 "raw".into(),
40 "bytes".into(),
41 #[cfg(feature = "fpml")]
42 "fpml".into(),
43 ],
44 ..crate::schema::resolution::SchemaCapabilities::declared(false)
45 },
46 name: "ibmmq".to_string(),
47 display_name: "IBM MQ Source".to_string(),
48 version: env!("CARGO_PKG_VERSION").to_string(),
49 is_source: true,
50 is_sink: false,
51 config_keys: source_config_keys(),
52 };
53 registry.register_source(
54 "ibmmq",
55 info,
56 Arc::new(|registry| {
57 Ok(Box::new(IbmMqSource::new(
58 Arc::new(Schema::empty()),
59 registry.map(Arc::as_ref),
60 )))
61 }),
62 )
63}
64
65pub fn register_ibmmq_sink(
71 registry: &ConnectorRegistry,
72) -> Result<(), crate::error::ConnectorError> {
73 let info = ConnectorInfo {
74 schema_capabilities: crate::schema::resolution::SchemaCapabilities::declared(true),
75 name: "ibmmq".to_string(),
76 display_name: "IBM MQ Sink".to_string(),
77 version: env!("CARGO_PKG_VERSION").to_string(),
78 is_source: false,
79 is_sink: true,
80 config_keys: sink_config_keys(),
81 };
82 registry.register_sink(
83 "ibmmq",
84 info,
85 Arc::new(|_config, registry| {
86 Ok(Box::new(IbmMqSink::new(
87 Arc::new(Schema::empty()),
88 registry.map(Arc::as_ref),
89 )))
90 }),
91 )
92}
93
94fn connection_keys() -> Vec<ConfigKeySpec> {
95 use ConfigKeySpec as K;
96 vec![
97 K::optional("queue.manager", "Queue manager name (MQCONNX)", ""),
98 K::optional(
99 "channel",
100 "Server-connection channel (MQCD ChannelName)",
101 "",
102 ),
103 K::optional(
104 "connection.name",
105 "CONNAME list host(port)[,host(port)] (MQCD ConnectionName)",
106 "",
107 ),
108 K::optional(
109 "ccdt.url",
110 "Client channel definition table URL (MQCNO CCDTUrl)",
111 "",
112 ),
113 K::optional("username", "MQCSP user", ""),
114 K::optional(
115 "password",
116 "MQCSP password; use a ${ENV} secret reference",
117 "",
118 ),
119 K::optional("application.name", "MQCNO application name", "laminardb"),
120 K::optional(
121 "tls.cipher.spec",
122 "SSLCIPH CipherSpec, e.g. ANY_TLS13_OR_HIGHER",
123 "",
124 ),
125 K::optional(
126 "tls.key.repository",
127 "Key repository (MQSCO KeyRepository)",
128 "",
129 ),
130 K::optional(
131 "tls.key.repository.password",
132 "Key repository password (secret)",
133 "",
134 ),
135 K::optional("tls.certificate.label", "Client certificate label", ""),
136 K::optional(
137 "tls.peer.name",
138 "SSLPEER filter the server certificate must match",
139 "",
140 ),
141 K::optional(
142 "reconnect",
143 "disabled | qmgr | any (MQCNO reconnect; the source supports disabled only)",
144 "disabled",
145 ),
146 K::optional("client.library", "Path to the IBM MQ client libmqm_r", ""),
147 K::optional(
148 "operation.timeout.ms",
149 "How long one MQI operation may take before the generation is abandoned",
150 "30000",
151 ),
152 ]
153}
154
155fn source_config_keys() -> Vec<ConfigKeySpec> {
156 use ConfigKeySpec as K;
157 let mut keys = connection_keys();
158 keys.extend([
159 K::required("queue", "Queue to get from under syncpoint"),
160 K::optional(
161 "wait.interval.ms",
162 "MQGMO WaitInterval for the first message of a poll",
163 "100",
164 ),
165 K::optional(
166 "max.message.bytes",
167 "Receive buffer; longer messages are never truncated",
168 "4194304",
169 ),
170 K::optional("max.batch.bytes", "Payload bytes per poll", "16777216"),
171 K::optional(
172 "max.uow.messages",
173 "Messages per unit of work before intake waits for a checkpoint",
174 "10000",
175 ),
176 K::optional(
177 "max.uow.bytes",
178 "Payload bytes per unit of work before intake waits for a checkpoint",
179 "67108864",
180 ),
181 K::optional(
182 "on.decode.error",
183 "fail | backout-queue (move to BOQNAME in the same unit of work)",
184 "fail",
185 ),
186 K::optional(
187 "convert",
188 "MQGMO_CONVERT to UTF-8 for convertible formats",
189 "false",
190 ),
191 K::optional(
192 "metadata.columns",
193 "Comma-separated MQMD/property columns (msg_id, correl_id, group_id, msg_seq_number, \
194 msg_flags, msg_type, format, ccsid, encoding, persistence, priority, expiry, \
195 backout_count, reply_to_queue, reply_to_queue_manager, put_timestamp, \
196 put_application_name, user_identifier, properties)",
197 "",
198 ),
199 ]);
200 #[cfg(feature = "fpml")]
201 keys.extend(crate::fpml::message::config_keys());
202 keys
203}
204
205fn sink_config_keys() -> Vec<ConfigKeySpec> {
206 use ConfigKeySpec as K;
207 let mut keys = connection_keys();
208 keys.extend([
209 K::required("queue", "Target queue"),
210 K::optional(
211 "target.queue.manager",
212 "MQOD ObjectQMgrName for a remote queue",
213 "",
214 ),
215 K::optional(
216 "persistence",
217 "persistent | not-persistent | as-queue-definition",
218 "persistent",
219 ),
220 K::optional("priority", "Literal MQMD Priority (0-9)", ""),
221 K::optional("priority.column", "Integer column for MQMD Priority", ""),
222 K::optional("expiry", "MQMD Expiry in tenths of a second", ""),
223 K::optional(
224 "message.id.column",
225 "Binary/Utf8 column for MsgId (else a new id)",
226 "",
227 ),
228 K::optional(
229 "correlation.id.column",
230 "Binary/Utf8 column for CorrelId",
231 "",
232 ),
233 K::optional("reply.to.queue", "MQMD ReplyToQ", ""),
234 K::optional("reply.to.queue.manager", "MQMD ReplyToQMgr", ""),
235 K::optional(
236 "message.format",
237 "MQMD Format override (defaults by codec)",
238 "",
239 ),
240 K::optional("ccsid", "MQMD CodedCharSetId of text payloads", "1208"),
241 K::optional(
242 "property.columns",
243 "Columns written as typed message properties",
244 "",
245 ),
246 K::optional(
247 "max.uow.messages",
248 "Messages per committed unit of work",
249 "1000",
250 ),
251 ]);
252 keys
253}