surrealdb / surrealdb.js

SurrealDB SDK for JavaScript
https://surrealdb.com
Apache License 2.0
272 stars 45 forks source link

Bug: Using docker compose networking causes TypeError: t.mask is not a function or connection to hang when running .wait() or .query() #216

Open NexVeridian opened 5 months ago

NexVeridian commented 5 months ago

Describe the bug

When using next.js 14.1.0 within a docker container and docker surrealdb/surrealdb:latest-dev

using a docker url name

db.connect("ws://surrealdb:8000/rpc");

Docker compose file

``` # .env DB_URL_PORT=surrealdb:8000 DB_USER=root DB_PASSWORD=root ``` ``` version: "3" services: nextjs: build: . env_file: - .env ports: - 3000:3000 depends_on: - surrealdb networks: - surrealdb-network surrealdb: container_name: surrealdb image: surrealdb/surrealdb:latest-dev env_file: - .env entrypoint: - /surreal - start - --user - $DB_USER - --pass - $DB_PASSWORD - file:/data/surrealdb restart: always ports: - 8000:8000 volumes: - ./data:/data networks: - surrealdb-network volumes: data: networks: surrealdb-network: ```

causes the following error when running npm run build CMD ["node", "server.js"], from within the next.js docker

TypeError: t.mask is not a function
    at e.exports.mask (/app/.next/server/chunks/235.js:1:59645)
    at h.frame (/app/.next/server/chunks/235.js:1:78447)
    at h.send (/app/.next/server/chunks/235.js:1:80497)
    at L.send (/app/.next/server/chunks/235.js:2:9182)
    at o.send (/app/.next/server/chunks/235.js:2:16756)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

docker file

``` # https://nextjs.org/docs/pages/building-your-application/deploying#docker-image FROM node:20-alpine AS base # Install dependencies only when needed FROM base AS deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /app # Install dependencies based on the preferred package manager COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ RUN \ if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ elif [ -f package-lock.json ]; then npm ci; \ elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ else echo "Lockfile not found." && exit 1; \ fi # Rebuild the source code only when needed FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Next.js collects completely anonymous telemetry data about general usage. # Learn more here: https://nextjs.org/telemetry # Uncomment the following line in case you want to disable telemetry during the build. ENV NEXT_TELEMETRY_DISABLED 1 # RUN yarn build # If using npm comment out above and use below instead RUN npm install RUN npm run build # Production image, copy all the files and run next FROM base AS runner WORKDIR /app ENV NODE_ENV production # Uncomment the following line in case you want to disable telemetry during runtime. ENV NEXT_TELEMETRY_DISABLED 1 RUN addgroup --system --gid 1001 nodejs RUN adduser --system --uid 1001 nextjs # COPY --from=builder /app/public ./public # Automatically leverage output traces to reduce image size # https://nextjs.org/docs/advanced-features/output-file-tracing COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs EXPOSE 3000 ENV PORT 3000 CMD ["node", "server.js"] ```

Or causes the connection to hang when using CMD ["npm ", "run", "dev"] from within the next.js docker file

docker file

``` # https://nextjs.org/docs/pages/building-your-application/deploying#docker-image FROM node:20-alpine AS base # Install dependencies only when needed FROM base AS deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /app # Install dependencies based on the preferred package manager COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ RUN \ if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ elif [ -f package-lock.json ]; then npm ci; \ elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ else echo "Lockfile not found." && exit 1; \ fi # Rebuild the source code only when needed FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Next.js collects completely anonymous telemetry data about general usage. # Learn more here: https://nextjs.org/telemetry # Uncomment the following line in case you want to disable telemetry during the build. ENV NEXT_TELEMETRY_DISABLED 1 # RUN yarn build # If using npm comment out above and use below instead RUN npm install RUN npm run build CMD ["npm ", "run", "dev"] ```

Other notes

Steps to reproduce

run this with the docker compose file from above

import { Surreal } from "surrealdb.js";
db.connect("ws://surrealdb:8000/rpc", {
      namespace: "url",
      database: "url",
      auth: {
        username: root,
        password: root,
      },
    }
console.log(db);
let res = await db.query(`
    select * from test 
    `);

For a runnable example see

https://github.com/NexVeridian/next-url-shortener at this route http://localhost:3000/stats

and look at these two code file, which is also the same as the above code

https://github.com/NexVeridian/next-url-shortener/blob/main/src/components/db-utils.tsx https://github.com/NexVeridian/next-url-shortener/blob/main/src/app/stats/db.tsx

Full logs with console.log(db) before the query

``` Attaching to nextjs-1, surrealdb surrealdb | surrealdb | .d8888b. 888 8888888b. 888888b. surrealdb | d88P Y88b 888 888 'Y88b 888 '88b surrealdb | Y88b. 888 888 888 888 .88P surrealdb | 'Y888b. 888 888 888d888 888d888 .d88b. 8888b. 888 888 888 8888888K. surrealdb | 'Y88b. 888 888 888P' 888P' d8P Y8b '88b 888 888 888 888 'Y88b surrealdb | '888 888 888 888 888 88888888 .d888888 888 888 888 888 888 surrealdb | Y88b d88P Y88b 888 888 888 Y8b. 888 888 888 888 .d88P 888 d88P surrealdb | 'Y8888P' 'Y88888 888 888 'Y8888 'Y888888 888 8888888P' 8888888P' surrealdb | surrealdb | surrealdb | 2024-02-18T14:53:16.757212Z INFO surreal::env: Running 1.2.1 for linux on x86_64 surrealdb | 2024-02-18T14:53:16.757245Z WARN surreal::dbs: ❌🔒 IMPORTANT: Authenticatio n is disabled. This is not recommended for production use. 🔒❌ surrealdb | 2024-02-18T14:53:16.757258Z INFO surrealdb_core::kvs::ds: Starting kvs store at file:///data/surrealdb surrealdb | 2024-02-18T14:53:17.308290Z INFO surrealdb_core::kvs::ds: Started kvs store at file:///data/surrealdb surrealdb | 2024-02-18T14:53:17.310273Z WARN surrealdb_core::kvs::ds: Credentials were provided, but existing root users were found. The root user 'root' will not be created surrealdb | 2024-02-18T14:53:17.310287Z WARN surrealdb_core::kvs::ds: Consider removing the --user and --pass arguments from the server start command surrealdb | 2024-02-18T14:53:17.310295Z INFO surrealdb::node: Started node agent surrealdb | 2024-02-18T14:53:17.312579Z INFO surrealdb::net: Started web server on 0.0.0.0:8000 nextjs-1 | ▲ Next.js 14.1.0 nextjs-1 | - Local: http://a608860dff66:3000 nextjs-1 | - Network: http://172.21.0.3:3000 nextjs-1 | nextjs-1 | ✓ Ready in 119ms nextjs-1 | l { nextjs-1 | socket: o { nextjs-1 | url: 'ws://surrealdb:8000/rpc', nextjs-1 | hooks: { nextjs-1 | onConnect: [AsyncFunction: onConnect], nextjs-1 | onClose: [Function: onClose], nextjs-1 | onError: undefined nextjs-1 | }, nextjs-1 | ws: L { nextjs-1 | _events: [Object: null prototype], nextjs-1 | _eventsCount: 4, nextjs-1 | _maxListeners: undefined, nextjs-1 | _binaryType: 'nodebuffer', nextjs-1 | _closeCode: 1006, nextjs-1 | _closeFrameReceived: false, nextjs-1 | _closeFrameSent: false, nextjs-1 | _closeMessage: , nextjs-1 | _closeTimer: null, nextjs-1 | _extensions: {}, nextjs-1 | _paused: false, nextjs-1 | _protocol: '', nextjs-1 | _readyState: 0, nextjs-1 | _receiver: null, nextjs-1 | _sender: null, nextjs-1 | _socket: null, nextjs-1 | _bufferedAmount: 0, nextjs-1 | _isServer: false, nextjs-1 | _redirects: 0, nextjs-1 | _autoPong: true, nextjs-1 | _url: 'ws://surrealdb:8000/rpc', nextjs-1 | _req: [ClientRequest], nextjs-1 | [Symbol(shapeMode)]: false, nextjs-1 | [Symbol(kCapture)]: false nextjs-1 | }, nextjs-1 | status: 1, nextjs-1 | queue: {}, nextjs-1 | liveQueue: {}, nextjs-1 | unprocessedLiveResponses: {}, nextjs-1 | ready: Promise { nextjs-1 | , nextjs-1 | [Symbol(async_id_symbol)]: 157, nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142, nextjs-1 | [Symbol(kResourceStore)]: [Object], nextjs-1 | [Symbol(kResourceStore)]: [Object], nextjs-1 | [Symbol(kResourceStore)]: [Object] nextjs-1 | }, nextjs-1 | closed: Promise { nextjs-1 | , nextjs-1 | [Symbol(async_id_symbol)]: 151, nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142, nextjs-1 | [Symbol(kResourceStore)]: [Object], nextjs-1 | [Symbol(kResourceStore)]: [Object], nextjs-1 | [Symbol(kResourceStore)]: [Object] nextjs-1 | }, nextjs-1 | resolveClosed: [Function (anonymous)], nextjs-1 | socketClosureReason: { '1000': 'CLOSE_NORMAL' } nextjs-1 | }, nextjs-1 | pinger: n { pinger: undefined, interval: 30000 }, nextjs-1 | connection: { nextjs-1 | auth: { username: 'root', password: 'root' }, nextjs-1 | namespace: 'url', nextjs-1 | database: 'url' nextjs-1 | }, nextjs-1 | ready: Promise { nextjs-1 | , nextjs-1 | [Symbol(async_id_symbol)]: 149, nextjs-1 | [Symbol(trigger_async_id_symbol)]: 142, nextjs-1 | [Symbol(kResourceStore)]: { nextjs-1 | headers: [Getter], nextjs-1 | cookies: [Getter], nextjs-1 | mutableCookies: [Getter], nextjs-1 | draftMode: [Getter] nextjs-1 | }, nextjs-1 | [Symbol(kResourceStore)]: { nextjs-1 | isStaticGeneration: false, nextjs-1 | urlPathname: '/stats', nextjs-1 | pagePath: '/stats/page', nextjs-1 | incrementalCache: [IncrementalCache], nextjs-1 | isRevalidate: true, nextjs-1 | isPrerendering: undefined, nextjs-1 | fetchCache: 'default-no-store', nextjs-1 | isOnDemandRevalidate: false, nextjs-1 | isDraftMode: false, nextjs-1 | postpone: undefined, nextjs-1 | fetchMetrics: [] nextjs-1 | }, nextjs-1 | [Symbol(kResourceStore)]: { isAction: true } nextjs-1 | }, nextjs-1 | resolveReady: [Function (anonymous)], nextjs-1 | rejectReady: [Function (anonymous)], nextjs-1 | strategy: 'ws', nextjs-1 | hooks: {} nextjs-1 | } nextjs-1 | TypeError: t.mask is not a function nextjs-1 | at e.exports.mask (/app/.next/server/chunks/235.js:1:59645) nextjs-1 | at h.frame (/app/.next/server/chunks/235.js:1:78447) nextjs-1 | at h.send (/app/.next/server/chunks/235.js:1:80497) nextjs-1 | at L.send (/app/.next/server/chunks/235.js:2:9182) nextjs-1 | at o.send (/app/.next/server/chunks/235.js:2:16756) nextjs-1 | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) ```

db.query causes the TypeError: t.mask is not a function, db.create is ok

Expected behaviour

The query should run

SurrealDB version

1.2.1, docker surrealdb/surrealdb:latest-dev

SurrealDB.js version

0.11.0

Contact Details

nexveridian@gmail.com

Is there an existing issue for this?

Code of Conduct

kearfy commented 5 months ago

Hey @NexVeridian, it is quite possible that the docker image used for building nextjs ships an old version of NodeJS out of the box, which probably lacks certain functionality, and which is likely different from the version of NodeJS installed on your system. I've never really tested it, but my guess would be that anything above NodeJS v16 will work, but while you're at it you might aswell set it to node 18 or 20 😃

NexVeridian commented 5 months ago

I think I have an update to date version FROM node:20-alpine AS base

I just swapped it to FROM node:20-bookworm AS base both have the same TypeError: t.mask is not a function as above

here is the full docker file, same as the one from the next.js docs

# https://nextjs.org/docs/pages/building-your-application/deploying#docker-image
FROM node:20-alpine AS base

# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi

# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1

# RUN yarn build
# If using npm comment out above and use below instead
RUN npm install
RUN npm run build

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# COPY --from=builder /app/public ./public

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["node", "server.js"]