使用两个不同的连接和相同的模型文件时关闭连接

问题描述 投票:0回答:1

我的续集设置遇到了一些困难,正在寻求一些指导/帮助。

我正在处理的场景如下:

  1. Electronjs 应用程序有两个续集连接:sqlite 和 mssql。
  2. sqlite 连接是在应用程序启动时构建的 - 工作正常。
  3. 当用户请求建立连接时,MSSQL 就会被连接 - 这似乎也工作正常。
  4. 用户可以“关闭”MSSQL 连接,因此应用程序需要回退到 sqlite 连接。这就是问题所在......

简而言之,sqlite 是“离线”工作区域,但是当用户连接到实时系统时,数据需要迁移,但会成为应用程序的工作连接,以便他们可以继续“在线”编辑内容。但是,用户可能决定与实时服务器“断开连接”,因此应用程序需要恢复到 sqlite 数据库。

实时服务器是“可配置的”,因此可能需要创建多个“实时”连接,因此我无法在启动时创建它,然后永远保留它,用户可以在两个不同的实时服务器之间切换。

但是,由于实时数据库和离线数据库都是彼此的副本,因此我有一组模型定义,并且希望在连接/断开连接时基本上“交换”续集连接。这就是我现在所拥有的:

'use strict';

const {
    app,
} = require('electron');
const logger = require('electron-log');

const path = require('path');
const {
    Sequelize, Op,
} = require('sequelize');

const userData = app.getPath('userData');
const dbFile = path.resolve(userData, 'library_v2.sqlite');
logger.debug(dbFile);

import {
    SequelizeStorage, Umzug, 
} from 'umzug';

const db = {
};

// Define the 'default' sqlite connection:
const sequelize = new Sequelize({
    dialect: 'sqlite',
    retry: {
        max: 50,
    },
    storage: dbFile,
    logging: msg => logger.debug(msg),
});

// Init the mssql connection:
let mssqlConnection = null;

// This is my connect function which works:
export const connect = (config, data) => {
    mssqlConnection = new Sequelize(config.database, config.username, config.password, {
        dialect: 'mssql',
        retry: {
            max: 5,
        },
        host: config.host,
        port: config.port,
        logging: msg => logger.debug(msg),
    });

    Object.values(db.sequelize.models)
        .forEach(model => {
            // Swap out the sequelize connection:
            model.sequelize = mssqlConnection;
        });

    ...

    db.sequelize = mssqlConnection;
    db.Sequelize = Sequelize;
    db.Op = Op;

    ...

    // Run the migration and seeds:
    const check = initialiseDatabase(mssqlConnection);
    return check.then(() => {
        return true;
    });
};

// This is my disconnect function which doesn't work... maybe...
export const disconnect = async () => {
    console.log('Disconnecting');
    await mssqlConnection.close();
    ...
    PT = null;
    mssqlConnection = null;

    // Reset the sequelize to the sqlite:
    Object.values(db.sequelize.models)
        .forEach(model => {
            model.sequelize = sequelize;
        });

    db.sequelize = sequelize;
    db.Sequelize = Sequelize;
    db.Op = Op;

    ...

    return true;
};
...

// Staging models:
db.Modules = require('./modules')(sequelize, Sequelize.DataTypes);
db.Sequences = require('./sequences')(sequelize, Sequelize.DataTypes);
...

Object.keys(db)
    .forEach(async (modelName) => {
        if (db[modelName].associate) {

            db[modelName].associate(db);
        }
    });
...

db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.Op = Op;

...

export default db;

连接似乎工作正常,我可以使用新连接来处理数据,但是当我尝试断开连接时,据我所知,一切都已“重置”以使用原始 sqlite 数据库,但出现错误抛出:

Error: ConnectionManager.getConnection was called after the connection manager was closed!
    at ConnectionManager.getConnection ([...]/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:74:13)
    at [...]/node_modules/sequelize/lib/sequelize.js:305:111
    at [...]/node_modules/retry-as-promised/dist/index.js:59:25
    at new Promise (<anonymous>)
    at retryAsPromised ([...]/node_modules/retry-as-promised/dist/index.js:48:12)
    at Timeout._onTimeout ([...]/node_modules/retry-as-promised/dist/index.js:94:21)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7)

从我的调试来看,我非常确定一切都已完成,但一旦我尝试从 sqlite 数据库“获取”数据,它就会抛出此错误。因此,似乎存在一个杂散的承诺,直到断开连接后才完成。

我已经检查了断开连接后“获取”新数据的模型,它显示了正确的续集连接 - 数据库的方言和文件 - 所以我相当确定它已断开连接。但是,获取失败,然后应用程序停止从数据库加载任何内容 - 所有模型的每次获取都报告相同的错误。唯一的解决方案是终止该应用程序并重新启动它。

有人知道我可能会错过什么吗?

注意:我已经稍微精简了代码,以删除大部分模型、使用 umzug 的迁移和播种器,以及一些续集修订跟踪(这些都有效,所以不认为它们是必要的),但没有编译错误。如果您认为可能还有其他原因,如果您认为需要,很乐意提供更多内容。

sql-server sqlite electron sequelize.js
1个回答
0
投票

经过多次尝试和错误,我偶然发现了“解决方案”,它可以归结为“顺序”。

为了使其正常工作,断开连接功能需要是:


// This is my disconnect function which doesn't work... maybe...
export const disconnect = async () => {
    // Apparently this needs to be before the .forEach:
    db.sequelize = sequelize;
    db.Sequelize = Sequelize;
    db.Op = Op;

    // Reset the sequelize to the sqlite:
    Object.values(db.sequelize.models)
        .forEach(model => {
            model.sequelize = sequelize;
        });

    console.log('Disconnecting');
    await mssqlConnection.close();
    ...
    PT = null;
    mssqlConnection = null;

    ...

    return true;
};

我不完全确定为什么这是有效的答案 - 我猜测在旧连接断开之前需要将模型重新分配给 sqlite 续集。否则,看起来他们会陷入某种困境,模型不确定连接到底是什么,并尝试使用断开的 mssql 连接。

© www.soinside.com 2019 - 2024. All rights reserved.