Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MongoDB Node.js Driver doesn't work when connecting to MongoDB Atlas from Deno #16633

Closed
alexbevi opened this issue Nov 14, 2022 · 32 comments
Closed
Labels
needs investigation requires further investigation before determining if it is an issue or not node compat

Comments

@alexbevi
Copy link

alexbevi commented Nov 14, 2022

Potentially related to issue #15824, but the mongodb driver cannot be used directly via Deno when targeting a MongoDB Atlas cluster. This was reported at NODE-4782 however it doesn't appear to be an issue with the Node driver itself.

// file: main.ts
import { MongoClient } from "mongodb"

const URI = "mongodb+srv://user:pass@cluster0.abcde.mongodb.net/test"
const client = new MongoClient(URI)

async function main() {
  console.log('connecting')  
  await client.connect()  
  console.log('connected')
  const collection = client.db('test_db').collection('test_collection')
  await collection.deleteMany({})
  await collection.insertOne({ a: 2.3 })
  var results = await collection.count({ a: 2.3 })
  console.log(`found ${results}`)
  process.exit(1)
}

main()

For example, when running the preceding using npx ts-node main.ts the script will connect to Atlas, authenticate/authorize, clear the collection, insert a new doc and execute a count.

connecting
connected
found 1

To make this run with Deno the script was updated as follows:

// file: main.ts
import { MongoClient } from 'npm:mongodb' // updated for Deno

const URI = "mongodb+srv://user:pass@cluster0.abcde.mongodb.net/test"
const client = new MongoClient(URI)

async function main() {
  console.log('connecting')  
  await client.connect()  
  console.log('connected')
  const collection = client.db('test_db').collection('test_collection')
  await collection.deleteMany({})
  await collection.insertOne({ a: 2.3 })
  var results = await collection.count({ a: 2.3 })
  console.log(`found ${results}`)
  process.exit(1)
}

main()

When the above script variation is run using deno run --unstable --allow-all main.ts it will fail with the following error as it doesn't appear to be able to resolve a DNS Seed List Connection String:

connecting
error: Uncaught MongoAPIError: Server record does not share hostname with parent URI
    at resolveSRVRecord (file:///Users/alex/Library/Caches/deno/npm/registry.npmjs.org/mongodb/4.11.0/lib/connection_string.js:62:19)
    at async file:///Users/alex/Library/Caches/deno/npm/registry.npmjs.org/mongodb/4.11.0/lib/mongo_client.js:120:31
    at async main (file:///Users/alex/temp/main.ts:17:3)

Changing the URI constant to use a Standard Connection String of mongodb://user:pass@cluster0-shard-00-00.abcde.mongodb.net:27017,cluster0-shard-00-01.abcde.mongodb.net:27017,cluster0-shard-00-02.abcde.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true&w=majority and re-running results in the operation just timing out:

connecting
error: Uncaught MongoServerSelectionError: connection timed out
    at Timeout.<anonymous> (file:///Users/alex/Library/Caches/deno/npm/registry.npmjs.org/mongodb/4.11.0/lib/sdam/topology.js:293:38)
    at https://deno.land/std@0.162.0/node/timers.ts:21:15
    at Object.action (deno:ext/web/02_timers.js:147:13)
    at handleTimerMacrotask (deno:ext/web/02_timers.js:64:12)

Note this was tested with:

deno 1.27.2 (release, x86_64-apple-darwin)
v8 10.8.168.4
typescript 4.8.3

Steps to Reproduce

  1. Sign up for a free M0 Atlas Cluster
  2. Get a Connection String (pick an older version of any driver to get the mongodb:// version instead of mongodb+srv://)
  3. Update the URI constant with your connection string
  4. deno run --unstable --allow-all main.ts
@alexbevi alexbevi changed the title MongoDB Node.js Driver doesn't work when connecting to MongoDB Atlas MongoDB Node.js Driver doesn't work when connecting to MongoDB Atlas from Deno Nov 14, 2022
@dsherret dsherret added needs investigation requires further investigation before determining if it is an issue or not node compat labels Nov 16, 2022
@ThePotatoChronicler
Copy link

The same error pops up on Linux x86_64 with Deno 1.28.1

@brendantang
Copy link

Same issue!

@NovqiGarrix
Copy link

Same issue here with Deno v1.28.2

@avalero
Copy link

avalero commented Feb 2, 2023

Same on Deno 1.30 and npm MongoDB 5.0.0

@alexbevi
Copy link
Author

alexbevi commented Feb 5, 2023

Note the MongoDB Node.js team has filed NODE-5042 which may address the "MongoAPIError: Server record does not share hostname with parent URI" portion of this issue.

@ImagiNFT
Copy link

ImagiNFT commented Feb 5, 2023

is there any solution for this?

@alexbevi
Copy link
Author

alexbevi commented Feb 7, 2023

Interesting development. Using a DNS Seed List in the URI appears to work correctly in the latest Deno:

$ deno --version
deno 1.30.3 (release, x86_64-apple-darwin)
v8 10.9.194.5
typescript 4.9.4
// file: main.ts
import { MongoClient } from 'npm:mongodb' // updated for Deno

const URI =
"mongodb://<user>:<pass>@cluster0-shard-00-00.abcde.mongodb.net:27017,cluster0-shard-00-01.abcde.mongodb.net:27017,cluster0-shard-00-02.abcde.mongodb.net:27017/?ssl=true&replicaSet=atlas-122v8z-shard-0&authSource=admin&retryWrites=true&w=majority"
const client = new MongoClient(URI)

async function main() {
  console.log('connecting')
  await client.connect()
  console.log('connected')
  const collection = client.db('test_db').collection('test_collection')
  await collection.deleteMany({})
  await collection.insertOne({ a: 2.3 })
  var results = await collection.count({ a: 2.3 })
  console.log(`found ${results}`)
  Deno.exit(1)
}

main()
connecting
connected
found 1

@mdmusaibali
Copy link

mdmusaibali commented Mar 19, 2023

This issue still remains on deno 1.31.3.
mongoose.connect connects successfully to mongodb localhost string but when given mongodb+srv string, connection fails with:

Cannot connect to DB MongoAPIError: Server record does not share hostname with parent URI
 at resolveSRVRecord (file:///home/mdmusaibali/.cache/deno/npm/registry.npmjs.org/mongodb/5.1.0/lib/connection_string.js:60:19)
    at async MongoClient.connect (file:///home/mdmusaibali/.cache/deno/npm/registry.npmjs.org/mongodb/5.1.0/lib/mongo_client.js:117:27)
    at async _createMongoClient (file:///home/mdmusaibali/.cache/deno/npm/registry.npmjs.org/mongoose/7.0.2/lib/connection.js:859:3)
    at async NativeConnection.openUri (file:///home/mdmusaibali/.cache/deno/npm/registry.npmjs.org/mongoose/7.0.2/lib/connection.js:728:5)
    at async file:///home/mdmusaibali/Documents/GitHub/pda-paper-validation-deno-ts/db/mongo.ts:6:5

Connection code:

import mongoose from "npm:mongoose@7.0.2";
try {
  const MONGO_URL = Deno.env.get("MONGO_URL");
  if (MONGO_URL) {
    await mongoose.connect(
      "mongodb+srv://<username>:<password>@cluster0.byaerrd.mongodb.net/<db-name>?retryWrites=true&w=majority"
    );
    console.log("Connected to db");
  }
} catch (error) {
  if (error instanceof Error) {
    console.log("Cannot connect to DB", error);
  }
}

@avalero
Copy link

avalero commented Mar 19, 2023

Damn! I hope this is fixed soon. It is very annoying not being able to work with mongo and Deno, and MongoDB Deno native library is abandoned and I think is does not support MongoDB v6

@jyemin
Copy link

jyemin commented Mar 19, 2023

@avalero can you clarify whether you are not able to using MongoDB at all with Deno, or if the issue is only with support for "mongodb+srv" connection string (see @alexbevi's comment just above).

@avalero
Copy link

avalero commented Mar 19, 2023

With the "mongodb+srv" connection string

@jyemin
Copy link

jyemin commented Mar 19, 2023

To get a non-SRV connection string, click the Connect button in the Atlas UI, choose the Node.js driver, and then select 2.2.12 or later. The connection string supplied for this version will work with all later versions of the Node.js driver and should also work with Deno.

Screen Shot 2023-03-19 at 12 00 06 PM

@hazelnutcloud
Copy link

hazelnutcloud commented Mar 24, 2023

I think I have figured out the source of this problem. When connecting with the mongodb+srv protocol, the node.js mongo driver compares the resolved SRV records against the parent domain.

To do that, it calls resolveSrv() function imported from node's dns module. Calling this API from Deno results in trailing dots in the name field of the objects in the array returned by the resolveSrv() function meanwhile running it node produces no trailing dots

Here's the code I used to test this:

import dns from "node:dns";

console.log(await dns.promises.resolveSrv("_mongodb._tcp.cluster.1abcd.mongodb.net"))

And here are the outputs when running in Deno:

[
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-01.1abcd.mongodb.net."
  },
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-02.1abcd.mongodb.net."
  },
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-00.1abcd.mongodb.net."
  }
]

in node:

[
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-01.1abcd.mongodb.net"
  },
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-02.1abcd.mongodb.net"
  },
  {
    priority: 0,
    weight: 0,
    port: 27017,
    name: "cluster-shard-00-00.1abcd.mongodb.net"
  }
]

I edited all the hostnames displayed there to hide some info but that's what it should look like.

@bartlomieju @crowlKats

@hazelnutcloud
Copy link

calling Deno.resolveDns("...", "SRV") also results in the same behavior (produces trailing dots)

@alexbevi
Copy link
Author

@hazelnutcloud from a MongoDB Driver POV a bug for this was reported previously (see NODE-5042) which we're hoping to get sorted out soon.

It's really helpful to see further confirmation that resolving this bug should improve the Deno experience using MongoDB!

@bartlomieju
Copy link
Member

Thanks for investigating @hazelnutcloud, @crowlKats is looking into this issue and it should be fixed in the coming days.

@eikooc
Copy link

eikooc commented Apr 13, 2023

Just chiming in with an update. The ticket over at MongoDB's Jira is marked as done with fix version v5.3.0.

https://jira.mongodb.org/browse/NODE-5042

@alexbevi
Copy link
Author

@eikooc you beat me to it :) The MongoDB Node Driver team addressed this with mongodb/node-mongodb-native@051b861, which will be included in the next release of the driver.

I'll close this issue out once the release is made :)

@alexbevi
Copy link
Author

FYI https://github.com/mongodb/node-mongodb-native/releases/tag/v5.3.0 has been released, which includes the fixes to SRV resolution that were affecting Deno. There may still be an opportunity to address this behavior in Deno directly, but for now the MongoDB driver should work :)

@topperspal
Copy link

It now started connecting to MongoDB with npm:mongodb@5.6.0 from Atlas uri. I can use CRUD operations but it throws error after a few minutes

error: Uncaught Error: read ECONNRESET
    at __node_internal_captureLargerStackTrace (ext:deno_node/internal/errors.ts:89:11)
    at __node_internal_errnoException (ext:deno_node/internal/errors.ts:137:12)
    at TCP.onStreamRead [as onread] (ext:deno_node/internal/stream_base_commons.ts:205:24)
    at TCP.#read (ext:deno_node/internal_binding/stream_wrap.ts:223:18)
    at eventLoopTick (ext:core/01_core.js:183:11)

@eikooc
Copy link

eikooc commented Jul 10, 2023

@topperspal I experience the same thing

@TillaTheHun0
Copy link

I am experiencing the same issue as @topperspal on npm:mongodb@5.6.0 and Deno 1.35.0. At first, operations performed using the driver succeed, but then after a few minutes, I get that same ECONNRESET error which crashes the process.

Perhaps worth noting that 5.6.0 introduced support for Node 20, so maybe some regression with node compat?

@eikooc
Copy link

eikooc commented Jul 11, 2023

@TillaTheHun0 if you can create a minimal reproduction then there's this issue where you can post it #19078

I haven't been able to create a succesful minimal production showing the error.

@TillaTheHun0
Copy link

TillaTheHun0 commented Jul 11, 2023

@eikooc I posted a repo with steps to reproduce. I was only able to replicate with an Atlas Serverless Cluster, which seems correlated, but can't say for sure without digging deeper.

https://github.com/TillaTheHun0/deno-mongo-atlas-repro

@eikooc
Copy link

eikooc commented Aug 4, 2023

I've noticed that this happens every time the MongoDB cluster scales up or down so the connection is cut.

@eikooc
Copy link

eikooc commented Aug 29, 2023

I believe this has been fixed in v1.37 #20314.
Right now it is possible to update by running deno upgrade --canary

@bartlomieju
Copy link
Member

Thanks for checking @eikooc! Let's close the issue then.

@fro-profesional
Copy link

I jus tried on local an deploy and seems to be working with MongoDB Atlas serverless deno v1.37

import { MongoClient } from "npm:mongodb"
import { ulid } from "https://deno.land/std@0.202.0/ulid/mod.ts";

const client = new MongoClient("<url>")

client.connect();

Deno.serve(async () => {

  const data = await client.db("deno").collection("deno").insertOne({
    name: ulid()
  })

  return new Response(JSON.stringify({
    data
  }), {
    headers: { "Content-Type": "application/json" },
  })
})

@ryvwel
Copy link

ryvwel commented May 31, 2024

It now started connecting to MongoDB with npm:mongodb@5.6.0 from Atlas uri. I can use CRUD operations but it throws error after a few minutes

error: Uncaught Error: read ECONNRESET
    at __node_internal_captureLargerStackTrace (ext:deno_node/internal/errors.ts:89:11)
    at __node_internal_errnoException (ext:deno_node/internal/errors.ts:137:12)
    at TCP.onStreamRead [as onread] (ext:deno_node/internal/stream_base_commons.ts:205:24)
    at TCP.#read (ext:deno_node/internal_binding/stream_wrap.ts:223:18)
    at eventLoopTick (ext:core/01_core.js:183:11)

Does anyone experience this error yet? It happens so random i can't reproduce it locally, but my serverless service sometimes crashes because of this

UPD: according to my atlas metrics, it happens on server restarts, so nevermind

@alexbevi
Copy link
Author

alexbevi commented May 31, 2024

@ryvwel that's just a socket error, so "why" the connection was closed would need investigation (it's likely not a Deno, or even MongoDB issue). Note that MongoDB's drivers support automatic retryability of reads and writes so it's possible the associated operation may not have even failed (though you may see a logged error).

This is likely a transient network error, so handling the uncaught exception and allowing the driver's connection pool to heal itself should allow you to continue normal operations.

@bartlomieju bartlomieju reopened this May 31, 2024
@jantoney
Copy link

@ryvwel @topperspal
I think the issue around error: Uncaught Error: read ECONNRESET might be related to #21951
If correct, it is something around a CLOSE and ERROR event being out of order in Deno.

Further links to others in that issue

@bartlomieju
Copy link
Member

We believe this is now fixed with #21951. Please try with Deno v1.45.4 and let us know if the problem persists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation requires further investigation before determining if it is an issue or not node compat
Projects
None yet
Development

No branches or pull requests