Skip to content

Built-in support for message compression#181

Closed
snichme wants to merge 2 commits intomainfrom
built-in-compression
Closed

Built-in support for message compression#181
snichme wants to merge 2 commits intomainfrom
built-in-compression

Conversation

@snichme
Copy link
Copy Markdown
Member

@snichme snichme commented Dec 11, 2025

Adds support for the producer to compress the payload by specifying compression algorithm, supported algos are gzip, lz4 and snappy. Looked at adding zstd but didn't find any packages with a synchronous API.

The consumer automatically picks up how the payload is compressed and decompresses it.

Each package is optional and it will be lazy loaded if needed.

Support for gzip, lz4 and snappy
@carlhoerberg
Copy link
Copy Markdown
Member

I have had as a proud feature of this library that this is a 0 dependency library. Could we make the dependencies optional?

Comment thread src/amqp-channel.ts
* @param properties - properties to be published
* @param [mandatory] - if the message should be returned if there's no queue to be delivered to
* @param [immediate] - if the message should be returned if it can't be delivered to a consumer immediately (not supported in RabbitMQ)
* @param options - publish options including compression settings
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These methods should map closely to the protocol. Add compression to a high level client.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should build out BaseClient to have high level features like auto-reconnect, message coding, rpc client/server etc. Just like the ruby client. This is a WIP in that direction: #180

@baelter
Copy link
Copy Markdown
Member

baelter commented Dec 11, 2025

Nice! I agree with

These methods should map closely to the protocol. Add compression to a high level client.

IMHO we should build out BaseClient to have high level features like auto-reconnect, message coding, rpc client/server etc. Just like the ruby client. This is a WIP in that direction: #180

@snichme
Copy link
Copy Markdown
Member Author

snichme commented Dec 12, 2025

I have had as a proud feature of this library that this is a 0 dependency library. Could we make the dependencies optional?

They are, since they are specified as peerDependencies and peerDependenciesMeta->optional=true according to docs and https://medium.com/@ruben.alapont/advanced-npm-working-with-peer-dependencies-b7c43aa852d8 they will not be installed and the user have to install it (by adding the dependecy to their package.json) in order to use a compress.

@snichme
Copy link
Copy Markdown
Member Author

snichme commented Dec 12, 2025

Nice! I agree with

These methods should map closely to the protocol. Add compression to a high level client.

IMHO we should build out BaseClient to have high level features like auto-reconnect, message coding, rpc client/server etc. Just like the ruby client. This is a WIP in that direction: #180

@baelter sounds good, maybe combine this PR into #180 or at least base this branch on your

Comment thread src/amqp-compression.ts
Comment on lines +98 to +99
case "zstd":
return await this.loadZstd()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zstd is not available.

Comment thread src/amqp-message.ts
Comment on lines +63 to +74
if (!AMQPMessage.COMPRESSION_ENCODINGS.includes(encoding)) {
// Unknown encoding, return raw body
return this.body
}

const codec = compressionRegistry.getCodecSync(encoding)
if (!codec) {
throw new CompressionError(
`Cannot decompress message: codec '${encoding}' is not loaded. Ensure the codec was used for compression first.`,
encoding as "gzip" | "lz4" | "snappy" | "zstd",
)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, we can use type assertions methods so we don't need to do a typecast later.

Something along this lines:

function isKnownCompressionAlgorithm(algorithm: string): algorithm is CompressionAlgorithm {
  return COMPRESSION_ENCODINGS.includes(algorithm)
}

Comment thread src/amqp-compression.ts
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't see why we would bother handling the null type for missing codecs. Might as well just throw the compression error straight up in here wherever we return null?

Comment on lines +17 to +20
declare module "@mongodb-js/zstd" {
export function compress(data: Buffer): Promise<Buffer>
export function decompress(data: Buffer): Promise<Buffer>
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
declare module "@mongodb-js/zstd" {
export function compress(data: Buffer): Promise<Buffer>
export function decompress(data: Buffer): Promise<Buffer>
}

We don't use this zstd encoding anyway

Comment thread test/compression.ts
Comment on lines +230 to +234
if (!codec) {
console.log(`Skipping ${algorithm} test - codec not available`)
expect(true).toBe(true) // Ensure at least one assertion
return
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we expect all these algorithms to work?

@baelter
Copy link
Copy Markdown
Member

baelter commented Mar 9, 2026

closing in favor of #192

@baelter baelter closed this Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants