telefonicaid / iotagent-node-lib

Module to enable IoT Agent developers to build custom agents for their devices that can easily connect to NGSI Context Brokers
https://iotagent-node-lib.rtfd.io/
GNU Affero General Public License v3.0
60 stars 85 forks source link

Attempt to provision an unconnected MongoDB results in obscure null-pointer/undefined error message. #809

Open jason-fox opened 4 years ago

jason-fox commented 4 years ago

Problem

Imagine the following, I have an IoT Agent, but my database is not present:

version: "3.1"

volumes:
    mongodb: ~

services:
    iot-agent:
        image: fiware/iotagent-json
        hostname: iot-agent
        container_name: fiware-iot-agent
        expose:
            - "4041"
            - "7896"
        ports:
            - "4041:4041"
            - "7896:7896"
        environment:
            - "IOTA_CB_HOST=orion"
            - "IOTA_CB_PORT=1026"
            - "IOTA_NORTH_PORT=4041"
            - "IOTA_REGISTRY_TYPE=mongodb"
            - "IOTA_MONGO_HOST=mongodb"
            - "IOTA_MONGO_PORT=27017"
            - "IOTA_MONGO_DB=iotagent-json"
            - "IOTA_HTTP_PORT=7896"
            - "IOTA_PROVIDER_URL=http://iot-agent:4041"

At the moment the system will attempt to connect n times and throw appropriate errors on startup:

1937c3092b43 | op=IoTAgentNGSI.DbConn | srv=n/a | subsrv=n/a | msg=Attempting to connect to MongoDB instance. Attempt 5 | comp=IoTAgent
fiware-iot-agent | time=2019-09-19T08:06:51.684Z | lvl=ERROR | corr=28407af0-2871-46d8-b9b0-1937c3092b43 | trans=28407af0-2871-46d8-b9b0-1937c3092b43 | op=IoTAgentNGSI.DbConn | srv=n/a | subsrv=n/a | msg=MONGODB-001: Error trying to connect to MongoDB: MongoError: failed to connect to server [mongodb:27017] on first connect [MongoError: getaddrinfo ENOTFOUND mongodb mongodb:27017] | comp=IoTAgent
fiware-iot-agent | time=2019-09-19T08:06:51.685Z | lvl=ERROR | corr=28407af0-2871-46d8-b9b0-1937c3092b43 | trans=28407af0-2871-46d8-b9b0

However after the Nth failure, startup will continue regardless. I can then happily query the /iot/about (using it as a heartbeat) and assume everything is fine ... until I attempt to actually do anything with the database e.g. provision a service and the request unhelpfully returns the following:

{
    "name": "TypeError",
    "message": "Cannot read property 'findOne' of undefined"
}

and the log states:

fiware-iot-agent | time=2019-09-19T08:08:24.415Z | lvl=DEBUG | corr=5f66b80f-7035-4348-a058-024f88b75d52 | trans=5f66b80f-7035-4348-a058-024f88b75d52 | op=IoTAgentNGSI.GenericMiddlewares | srv=openiot | subsrv=/ | msg=Error [TypeError] handling request: Cannot read property 'findOne' of undefined | comp=IoTAgent

The reason for this failure is quite simple, mongoose cannot create the schema model since it can't connect to a non-existent database.

Solution

Since the IoT Agent is unusable, I guess the start-up should fail completely and exit if the database cannot connect.

The alternative would be to add an undefined check on each invocation of .model.findOne() and throw a more appropriate error message.

If we're going to fail, we might as well fail in an understandable manner.

jason-fox commented 4 years ago

I discovered this findOne error message by copy-pasting the yaml from the Docker README.md documentation directly - there is a repeated typo there which needs fixing since mongodb and mongo-db refer to different URLs:

The underlying issue needs to be addressed in the node library though.

tzzed commented 1 year ago

@jason-fox +1

fgalan commented 1 year ago

It would be great if somebody could contribute with a solution to this issue in the form of PR. It has been labeled with "help wanted". Thanks in advance!