@@ -116,6 +116,22 @@ class WorkerQueue: public jsg::Object {
116116
117117// Event handler types
118118
119+ // Metadata delivered with a message batch in the queue() handler
120+
121+ struct MessageBatchMetrics {
122+ double backlogCount;
123+ double backlogBytes;
124+ double oldestMessageTimestamp;
125+ JSG_STRUCT (backlogCount, backlogBytes, oldestMessageTimestamp);
126+ JSG_STRUCT_TS_OVERRIDE (MessageBatchMetrics);
127+ };
128+
129+ struct MessageBatchMetadata {
130+ MessageBatchMetrics metrics;
131+ JSG_STRUCT (metrics);
132+ JSG_STRUCT_TS_OVERRIDE (MessageBatchMetadata);
133+ };
134+
119135// Types for other workers passing messages into and responses out of a queue handler.
120136
121137struct IncomingQueueMessage {
@@ -235,6 +251,7 @@ class QueueEvent final: public ExtendableEvent {
235251 struct Params {
236252 kj::String queueName;
237253 kj::Array<IncomingQueueMessage> messages;
254+ MessageBatchMetadata metadata;
238255 };
239256
240257 explicit QueueEvent (jsg::Lock& js,
@@ -250,30 +267,45 @@ class QueueEvent final: public ExtendableEvent {
250267 kj::StringPtr getQueueName () {
251268 return queueName;
252269 }
270+ MessageBatchMetadata getMetadata () {
271+ return metadata;
272+ }
253273
254274 void retryAll (jsg::Optional<QueueRetryOptions> options);
255275 void ackAll ();
256276
257- JSG_RESOURCE_TYPE (QueueEvent) {
277+ JSG_RESOURCE_TYPE (QueueEvent, CompatibilityFlags::Reader flags ) {
258278 JSG_INHERIT (ExtendableEvent);
259279
260280 JSG_LAZY_READONLY_INSTANCE_PROPERTY (messages, getMessages);
261281 JSG_READONLY_INSTANCE_PROPERTY (queue, getQueueName);
262282
283+ if (flags.getWorkerdExperimental ()) {
284+ JSG_READONLY_INSTANCE_PROPERTY (metadata, getMetadata);
285+ }
286+
263287 JSG_METHOD (retryAll);
264288 JSG_METHOD (ackAll);
265289
266290 JSG_TS_ROOT ();
267- JSG_TS_OVERRIDE (QueueEvent<Body = unknown> {
268- readonly messages: readonly Message<Body>[];
269- });
291+ if (flags.getWorkerdExperimental ()) {
292+ JSG_TS_OVERRIDE (QueueEvent<Body = unknown> {
293+ readonly messages: readonly Message<Body>[];
294+ readonly metadata: MessageBatchMetadata;
295+ });
296+ } else {
297+ JSG_TS_OVERRIDE (QueueEvent<Body = unknown> {
298+ readonly messages: readonly Message<Body>[];
299+ });
300+ }
270301 }
271302
272303 void visitForMemoryInfo (jsg::MemoryTracker& tracker) const {
273304 for (auto & message: messages) {
274305 tracker.trackField (" message" , message);
275306 }
276307 tracker.trackField (" queueName" , queueName);
308+ tracker.trackFieldWithSize (" metadata" , sizeof (MessageBatchMetadata));
277309 tracker.trackFieldWithSize (" IoPtr<QueueEventResult>" , sizeof (IoPtr<QueueEventResult>));
278310 }
279311
@@ -297,6 +329,7 @@ class QueueEvent final: public ExtendableEvent {
297329 // array to avoid one intermediate copy?
298330 kj::Array<jsg::Ref<QueueMessage>> messages;
299331 kj::String queueName;
332+ MessageBatchMetadata metadata;
300333 IoPtr<QueueEventResult> result;
301334 CompletionStatus completionStatus = Incomplete{};
302335
@@ -316,24 +349,38 @@ class QueueController final: public jsg::Object {
316349 kj::StringPtr getQueueName () {
317350 return event->getQueueName ();
318351 }
352+ MessageBatchMetadata getMetadata () {
353+ return event->getMetadata ();
354+ }
319355 void retryAll (jsg::Optional<QueueRetryOptions> options) {
320356 event->retryAll (options);
321357 }
322358 void ackAll () {
323359 event->ackAll ();
324360 }
325361
326- JSG_RESOURCE_TYPE (QueueController) {
362+ JSG_RESOURCE_TYPE (QueueController, CompatibilityFlags::Reader flags ) {
327363 JSG_READONLY_INSTANCE_PROPERTY (messages, getMessages);
328364 JSG_READONLY_INSTANCE_PROPERTY (queue, getQueueName);
329365
366+ if (flags.getWorkerdExperimental ()) {
367+ JSG_READONLY_INSTANCE_PROPERTY (metadata, getMetadata);
368+ }
369+
330370 JSG_METHOD (retryAll);
331371 JSG_METHOD (ackAll);
332372
333373 JSG_TS_ROOT ();
334- JSG_TS_OVERRIDE (MessageBatch<Body = unknown> {
335- readonly messages: readonly Message<Body>[];
336- });
374+ if (flags.getWorkerdExperimental ()) {
375+ JSG_TS_OVERRIDE (MessageBatch<Body = unknown> {
376+ readonly messages: readonly Message<Body>[];
377+ readonly metadata: MessageBatchMetadata;
378+ });
379+ } else {
380+ JSG_TS_OVERRIDE (MessageBatch<Body = unknown> {
381+ readonly messages: readonly Message<Body>[];
382+ });
383+ }
337384 }
338385
339386 void visitForMemoryInfo (jsg::MemoryTracker& tracker) const {
@@ -400,8 +447,9 @@ class QueueCustomEvent final: public WorkerInterface::CustomEvent, public kj::Re
400447
401448#define EW_QUEUE_ISOLATE_TYPES \
402449 api::WorkerQueue, api::WorkerQueue::SendOptions, api::WorkerQueue::SendBatchOptions, \
403- api::WorkerQueue::MessageSendRequest, api::WorkerQueue::Metrics, api::IncomingQueueMessage, \
404- api::QueueRetryBatch, api::QueueRetryMessage, api::QueueResponse, api::QueueRetryOptions, \
405- api::QueueMessage, api::QueueEvent, api::QueueController, api::QueueExportedHandler
450+ api::WorkerQueue::MessageSendRequest, api::WorkerQueue::Metrics, api::MessageBatchMetrics, \
451+ api::MessageBatchMetadata, api::IncomingQueueMessage, api::QueueRetryBatch, \
452+ api::QueueRetryMessage, api::QueueResponse, api::QueueRetryOptions, api::QueueMessage, \
453+ api::QueueEvent, api::QueueController, api::QueueExportedHandler
406454
407455} // namespace workerd::api
0 commit comments