0

I'm trying to reduce the amount of times the database object is initialized in my data access file (variable database inside the file tree-rxdb.mjs). I created a global variable to hold a reference to the database object and check if it has been initialized before, if it has I just return the variable to the caller without initializing it again. For some reason, the database it's always undefined every time I call this function, even after I have successfully written to the database using the same code. Weirdly, the same doesn't happen to the dao variable inside tree.mjs even though I believe I'm giving it the same treatment but obviously getting differing results. I'm just emulating this code but for some reason it's not working out for the database variable inside tree-rxdb.mjs, what am I not seeing?

tree-rxdb.mjs

import RxDB from 'rxdb';
import adapter from 'pouchdb-adapter-leveldb'
import leveldown from 'leveldown'
import Log from '../utils/log.mjs';
const TAG = 'fruits-rxdb'

RxDB.plugin(adapter)

var database;

const treeSchema = {
    title: 'fruits schema',
    description: 'Describes a fruits tree',
    version: 0,
    type: 'object',
    properties: {
        name: { type: 'string' },
        desc: { type: 'string' },
        url: { type: 'string' },
        state: { 
            type: 'integer',
            enum: [0, 1]
        },
        favorite: {
            type: 'boolean'
        },
        dateAdded: { type: 'string' },
        userId: { type: 'string' }
    }
}

async function connectDB() {
    Log.debug(`Database object = ${database}`, TAG)
    if (database) return database;
    database = await RxDB.create({
        name: 'fruitsdb',
        adapter: leveldown,
        password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
    });
    await database.collection({
        name: 'trees',
        schema: treeSchema
    });
    Log.debug('Database has been initialized', TAG)
    return database;
}

export async function create(tree) {
    const db = await connectDB();
    db.trees.insert(tree.JSON);
}

tree.mjs

import util from 'util'
import logger from '../utils/log.mjs'
import Fruit from './Fruit.mjs'
const TAG = "tree-dao"

var dao;

async function model() {
    logger.debug(`DAO object = ${util.inspect(dao)}`, TAG)
    if(dao) return dao;
    dao = await import(`../dao/tree-${process.env.MODEL}`);
    logger.debug(`DAO model has been initialized: ${util.inspect(dao)}`, TAG);
    return dao;
}

export async function add(){
    const Fruit = new Fruit(undefined, 'Peach', 'peach 123',
        'http://something.com', 0, false, new Date().toISOString(), 'admin');
    (await model()).create(Fruit);
}

app.mjs

import express from 'express';
import logger from 'morgan'; 
import cookieParser from 'cookie-parser';
import bodyParser from 'body-parser';
import { default as fruits } from "./routes/fruits"
import * as tree from './models/tree.mjs'

const app = express();

app.use(logger("dev"));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use("/fruits", fruits);

const add = async () => {
    await tree.add();
    await tree.add();
    await tree.add();
};
add();

export default app

Aspiring Dev
  • 505
  • 1
  • 4
  • 17

3 Answers3

0

The problem is that database is only written when the promise of the creation is resolved. So calling connectDB multiple times will have database === undefined each time.

You should cache the creation-promise and return that from connectDB if it already exists.

Instead of

if (database) return database;
database = await RxDB.create({
    name: 'fruitsdb',
    adapter: leveldown,
    password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
});

do

if (database) return await database;
database = RxDB.create({
    name: 'fruitsdb',
    adapter: leveldown,
    password: (process.env.DB_PASSWORD || 'myfruitsJsPasswordTemp')
});
pubkey
  • 617
  • 8
  • 17
  • I understand that but isn't the creation promise resolved after the first `await tree.add()` is executed in app.mjs? I can confirm that the data is being inserted into the database so I know that the database creation promise has been fulfilled by the time the second and third `await tree.add()` is executed. Why isn't `database` holding the result of the fulfilled promise after that first successful invocation of `await tree.add()`? – Aspiring Dev Oct 17 '19 at 13:14
0

I was missing an await in tree.mjs. The line (await model()).create(Fruit); should be await (await model()).create(Fruit); the inner await was throwing me off. Now it's behaving like I expected it to.

Aspiring Dev
  • 505
  • 1
  • 4
  • 17
-1

In Node.js global scope is equal to the files' own scope. If you want to define a global variable accesible by all files at runtime, use global