Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .github/workflows/ci.common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,44 @@ jobs:
with:
persist-credentials: false

- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node ${{ inputs.node_version }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ inputs.node_version }}
package-manager-cache: false
cache: 'pnpm'

- name: Install
run: npm install --ignore-scripts
run: pnpm install --frozen-lockfile --ignore-scripts

- name: Build TS
env:
PACKAGE_NAME: ${{ inputs.package_name }}
run: npm run build -- --filter="$PACKAGE_NAME"
run: pnpm run build --filter="$PACKAGE_NAME"

- name: Run lint
env:
PACKAGE_NAME: ${{ inputs.package_name }}
run: npm run lint -- --filter="$PACKAGE_NAME"
run: pnpm run lint --filter="$PACKAGE_NAME"

- name: Docker start
env:
PACKAGE_NAME: ${{ inputs.package_name }}
QUEUE_BACKEND: ${{ inputs.queue_backend }}
run: npm run docker:start:ci -- --filter="$PACKAGE_NAME"
run: pnpm run docker:start:ci --filter="$PACKAGE_NAME"

- name: Run Tests
env:
PACKAGE_NAME: ${{ inputs.package_name }}
QUEUE_BACKEND: ${{ inputs.queue_backend }}
run: |
echo "::notice::Running $PACKAGE_NAME with QUEUE_BACKEND=$QUEUE_BACKEND"
npm run test:ci -- --filter="$PACKAGE_NAME"
pnpm run test:ci --filter="$PACKAGE_NAME"

- name: Docker stop
env:
PACKAGE_NAME: ${{ inputs.package_name }}
QUEUE_BACKEND: ${{ inputs.queue_backend }}
run: npm run docker:stop:ci -- --filter="$PACKAGE_NAME"
run: pnpm run docker:stop:ci --filter="$PACKAGE_NAME"
15 changes: 9 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -292,15 +292,18 @@ jobs:
- name: Pull latest changes
run: git pull --ff-only origin main

- name: Setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8

- name: Setup Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
registry-url: 'https://registry.npmjs.org'
package-manager-cache: false
cache: 'pnpm'

- name: Install dependencies
run: npm install --ignore-scripts
run: pnpm install --frozen-lockfile --ignore-scripts

- name: Bump versions for changed packages
id: bump
Expand All @@ -320,7 +323,7 @@ jobs:
echo "Bumping version for $PKG_NAME..."
cd "packages/$PKG_NAME"
OLD_VERSION=$(node -p "require('./package.json').version")
npm version "$BUMP" --no-git-tag-version
pnpm version "$BUMP" --no-git-tag-version
NEW_VERSION=$(node -p "require('./package.json').version")
echo " $OLD_VERSION -> $NEW_VERSION"

Expand All @@ -343,7 +346,7 @@ jobs:
run: |
for NPM_NAME in $(echo "$MATRIX" | jq -r '.[] | .npmName'); do
echo "Building $NPM_NAME..."
npm run build -- --filter="$NPM_NAME"
pnpm run build --filter="$NPM_NAME"
done

- name: Publish packages to npm
Expand All @@ -363,12 +366,12 @@ jobs:
VERSION=$(node -p "require('./package.json').version")

# Check if this version is already published (idempotent)
if npm view "$NPM_NAME@$VERSION" version >/dev/null 2>&1; then
if pnpm view "$NPM_NAME@$VERSION" version >/dev/null 2>&1; then
echo "Skipping $NPM_NAME@$VERSION - already published"
SKIPPED+="$NPM_NAME@$VERSION "
else
echo "Publishing $NPM_NAME@$VERSION..."
npm publish --provenance --access public
pnpm publish --provenance --access public --no-git-checks
PUBLISHED+="$NPM_NAME@$VERSION "
fi

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "@message-queue-toolkit/parent",
"version": "1.0.0",
"workspaces": ["packages/*"],
"scripts": {
"build": "turbo run build",
"lint": "turbo run lint --continue",
Expand All @@ -17,5 +16,5 @@
"devDependencies": {
"turbo": "^2.8.10"
},
"packageManager": "npm@10.7.0"
"packageManager": "pnpm@11.1.2"
}
6 changes: 3 additions & 3 deletions packages/amqp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"docker:start": "docker compose up -d --wait rabbitmq",
"docker:stop": "docker compose down",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/node-core": "^14.7.4"
Expand Down
6 changes: 3 additions & 3 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"prepublishOnly": "npm run lint && npm run build"
"test:coverage": "pnpm run test --coverage",
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/node-core": "^14.2.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/gcp-pubsub/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"docker:start": "docker compose up -d --quiet-pull --wait pubsub-emulator redis gcs-emulator",
"docker:stop": "docker compose down",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@grpc/grpc-js": "^1.14.2",
Expand Down
6 changes: 3 additions & 3 deletions packages/gcs-payload-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"docker:start": "docker compose up -d --quiet-pull --wait gcs-emulator",
"docker:stop": "docker compose down",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {},
"peerDependencies": {
Expand Down
18 changes: 13 additions & 5 deletions packages/kafka/lib/AbstractKafkaConsumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { randomUUID } from 'node:crypto'
import { pipeline } from 'node:stream/promises'
import { setTimeout } from 'node:timers/promises'
import {
copyWithoutUndefined,
InternalError,
isError,
resolveGlobalErrorLogObject,
Expand Down Expand Up @@ -124,7 +125,8 @@ export abstract class AbstractKafkaConsumer<
* During a reconnect attempt, returns `true` until all reconnect attempts are exhausted.
*/
get isConnected(): boolean {
if (!this.consumer) return this.isReconnecting
if (this.isReconnecting) return true
if (!this.consumer) return false
try {
return this.consumer.isConnected()
/* v8 ignore start */
Expand All @@ -141,7 +143,8 @@ export abstract class AbstractKafkaConsumer<
* During a reconnect attempt, returns `true` until all reconnect attempts are exhausted.
*/
get isActive(): boolean {
if (!this.consumer) return this.isReconnecting
if (this.isReconnecting) return true
if (!this.consumer) return false
try {
return this.consumer.isActive()
/* v8 ignore start */
Expand All @@ -158,10 +161,12 @@ export abstract class AbstractKafkaConsumer<
const topics = Object.keys(this.options.handlers)
if (topics.length === 0) throw new Error('At least one topic must be defined')

// Consumer needs to be recreated; once you call close, it ends in a final state, so we need to start from scratch
// Consumer needs to be recreated; once you call close, it ends in a final state, so we need to start from scratch.
// Undefined values must be stripped: as of @platformatic/kafka 2.1.0 they no longer override library defaults
// (see https://github.com/platformatic/kafka/issues/288), so leaving them in would silently re-apply defaults
// for connection-level options (e.g. requestTimeout) that callers expected to be controlled by `this.options.kafka`.
this.consumer = new Consumer({
...this.options.kafka,
...this.options,
...copyWithoutUndefined({ ...this.options.kafka, ...this.options }),
autocommit: false, // Handling commits manually
deserializers: {
key: stringDeserializer,
Expand Down Expand Up @@ -258,6 +263,9 @@ export abstract class AbstractKafkaConsumer<
}

private async reconnect(error: unknown): Promise<void> {
// Guard against re-entry: spurious stream errors (e.g. "Premature close" emitted by an
// already-being-replaced stream) must not start a second reconnect loop in parallel.
if (this.isReconnecting) return
this.isReconnecting = true
this.logger.info(
{ error: resolveGlobalErrorLogObject(error) },
Expand Down
8 changes: 5 additions & 3 deletions packages/kafka/lib/AbstractKafkaPublisher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { InternalError, stringValueSerializer } from '@lokalise/node-core'
import { copyWithoutUndefined, InternalError, stringValueSerializer } from '@lokalise/node-core'
import { MessageSchemaContainer } from '@message-queue-toolkit/core'
import {
jsonSerializer,
Expand Down Expand Up @@ -50,9 +50,11 @@ export abstract class AbstractKafkaPublisher<
})
}

// Undefined values must be stripped: as of @platformatic/kafka 2.1.0 they no longer override library defaults
// (see https://github.com/platformatic/kafka/issues/288), so leaving them in would silently re-apply defaults
// for connection-level options (e.g. requestTimeout) that callers expected to be controlled by `this.options.kafka`.
this.producer = new Producer({
...this.options.kafka,
...this.options,
...copyWithoutUndefined({ ...this.options.kafka, ...this.options }),
serializers: {
key: stringSerializer,
value: jsonSerializer,
Expand Down
8 changes: 4 additions & 4 deletions packages/kafka/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest run --typecheck",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"docker:start": "docker compose up -d kafka",
"docker:stop": "docker compose down",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/node-core": "^14.2.0",
"@lokalise/universal-ts-utils": "^4.5.1",
"@platformatic/kafka": "^2.0.1"
"@platformatic/kafka": "^2.1.0"
},
"peerDependencies": {
"@message-queue-toolkit/core": ">=23.0.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/kafka/test/consumer/PermissionBatchConsumer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ describe('PermissionBatchConsumer', () => {
clientId: randomUUID(),
connectTimeout: 10, // Short timeout to trigger failure quick
},
// platformatic-kafka >= 2.1.0 retries group ops by default; disable to fail fast
retries: 0,
})

// When - Then
Expand Down
2 changes: 2 additions & 0 deletions packages/kafka/test/consumer/PermissionBatchConsumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type PermissionBatchConsumerOptions = Partial<
| 'headerRequestIdField'
| 'messageIdField'
| 'batchProcessingOptions'
| 'retries'
>
>

Expand Down Expand Up @@ -81,6 +82,7 @@ export class PermissionBatchConsumer extends AbstractKafkaConsumer<
handlerSpy: options.handlerSpy ?? true,
headerRequestIdField: options.headerRequestIdField,
messageIdField: options.messageIdField,
retries: options.retries,
},
{
incrementAmount: 0,
Expand Down
2 changes: 2 additions & 0 deletions packages/kafka/test/consumer/PermissionConsumer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ describe('PermissionConsumer', () => {
clientId: randomUUID(),
connectTimeout: 10, // Short timeout to trigger failure quick
},
// platformatic-kafka >= 2.1.0 retries group ops by default; disable to fail fast
retries: 0,
})

// When - Then
Expand Down
2 changes: 2 additions & 0 deletions packages/kafka/test/consumer/PermissionConsumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type PermissionConsumerOptions = Partial<
| 'handlers'
| 'headerRequestIdField'
| 'messageIdField'
| 'retries'
>
>

Expand Down Expand Up @@ -75,6 +76,7 @@ export class PermissionConsumer extends AbstractKafkaConsumer<
handlerSpy: options.handlerSpy ?? true,
headerRequestIdField: options.headerRequestIdField,
messageIdField: options.messageIdField,
retries: options.retries,
maxWaitTime: 5,
},
{
Expand Down
6 changes: 3 additions & 3 deletions packages/metrics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"prepublishOnly": "npm run lint && npm run build"
"test:coverage": "pnpm run test --coverage",
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/node-core": "^14.2.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/outbox-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/background-jobs-common": "^14.0.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/redis-message-deduplication-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
"./package.json": "./package.json"
},
"scripts": {
"build": "npm run clean && tsc --project tsconfig.build.json",
"build": "pnpm run clean && tsc --project tsconfig.build.json",
"clean": "rimraf dist",
"test": "vitest",
"test:coverage": "npm run test -- --coverage",
"test:coverage": "pnpm run test --coverage",
"lint": "biome check . && tsc",
"lint:fix": "biome check --write .",
"docker:start": "docker compose up -d redis",
"docker:stop": "docker compose down",
"prepublishOnly": "npm run lint && npm run build"
"prepublishOnly": "pnpm run lint && pnpm run build"
},
"dependencies": {
"@lokalise/node-core": "^14.2.0",
Expand Down
Loading
Loading