-
-
Notifications
You must be signed in to change notification settings - Fork 907
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added connection manager and id helper functions
- Loading branch information
1 parent
08acd8c
commit 80318d3
Showing
10 changed files
with
278 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const Tenant = require('../models/Tenant'); | ||
const Database = require('../Database/index'); | ||
const { setConnection, getConnection } = require('./connections'); | ||
|
||
module.exports = async (organizationId) => { | ||
try { | ||
const alreadyConnected = getConnection(organizationId); | ||
if (alreadyConnected) return alreadyConnected; | ||
const [tenant] = await Tenant.find({ organization: organizationId }); | ||
if (!tenant || !tenant.url) throw new Error('Organization not found!'); | ||
console.log('tenant', tenant); | ||
let connection = new Database(tenant.url); | ||
await connection.connect(); | ||
setConnection(tenant.organization, connection); | ||
return connection; | ||
} catch (e) { | ||
console.log('organization not found!'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const connections = {}; | ||
|
||
const setConnection = (orgId, connection) => { | ||
connections[`${orgId}`] = connection; | ||
}; | ||
|
||
const getConnection = (orgId) => { | ||
if (!connections[orgId]) return null; | ||
return connections[orgId]; | ||
}; | ||
|
||
const destroy = async () => { | ||
for (let conn in connections) { | ||
await connections[conn].disconnect(); | ||
delete connections[conn]; | ||
} | ||
}; | ||
|
||
module.exports = { setConnection, getConnection, destroy }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const connections = require('./connections'); | ||
|
||
module.exports = async () => { | ||
try { | ||
await connections.destroy(); | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const { getConnection } = require('./connections'); | ||
|
||
module.exports = (organizationId) => { | ||
try { | ||
return getConnection(organizationId); | ||
} catch (e) { | ||
console.log('organization not found!'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const addTenantConnection = require('./addTenantConnection'); | ||
const getTenantConnection = require('./getTenantConnection'); | ||
const initTenants = require('./initTenants'); | ||
const destroyConnections = require('./destroyConnections'); | ||
|
||
module.exports = { | ||
addTenantConnection, | ||
getTenantConnection, | ||
initTenants, | ||
destroyConnections, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
const Tenant = require('../models/Tenant'); | ||
const Database = require('../Database/index'); | ||
const { setConnection } = require('./connections'); | ||
|
||
module.exports = async () => { | ||
try { | ||
const databases = await Tenant.find(); | ||
for (let db of databases) { | ||
let connection = new Database(db.url); | ||
await connection.connect(); | ||
setConnection(db.organization, connection); | ||
} | ||
} catch (e) { | ||
console.log('connection failed'); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = (tenantId, id) => { | ||
return tenantId + ' ' + id; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module.exports = (fullId) => { | ||
const [tenantId, id] = fullId.split(' '); | ||
return { tenantId, id }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const mongoose = require('mongoose'); | ||
const Schema = mongoose.Schema; | ||
|
||
const tenantSchema = new Schema({ | ||
organization: { | ||
type: Schema.Types.ObjectId, | ||
ref: 'Organizaiton', | ||
}, | ||
url: { | ||
type: String, | ||
required: true, | ||
}, | ||
type: { | ||
type: String, | ||
enum: ['MONGO', 'POSTGRES'], | ||
default: 'MONGO', | ||
required: true, | ||
}, | ||
status: { | ||
type: String, | ||
required: true, | ||
default: 'ACTIVE', | ||
enum: ['ACTIVE', 'BLOCKED', 'DELETED'], | ||
}, | ||
createdAt: { | ||
type: Date, | ||
default: Date.now, | ||
}, | ||
}); | ||
|
||
module.exports = mongoose.model('Tenant', tenantSchema); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
const shortid = require('shortid'); | ||
const Tenant = require('../../lib/models/Tenant'); | ||
const connectionManager = require('../../lib/ConnectionManager'); | ||
|
||
const database = require('../../db'); | ||
const getUserIdFromSignUp = require('../functions/getUserIdFromSignup'); | ||
const Organization = require('../../lib/models/Organization'); | ||
const User = require('../../lib/models/User'); | ||
// const Post = require('../../lib/models/Post'); | ||
const tenantUrl = | ||
'mongodb://localhost:27017/org1-tenant?retryWrites=true&w=majority'; | ||
const secondTenantUrl = | ||
'mongodb://localhost:27017/org2-tenant?retryWrites=true&w=majority'; | ||
|
||
let adminId; | ||
let organizationId; | ||
let secondOrganizationId; | ||
|
||
beforeAll(async () => { | ||
// setting up 1 org, one user with 1 tenant record (on the main database). | ||
require('dotenv').config(); | ||
await database.connect(); | ||
|
||
const adminEmail = `${shortid.generate().toLowerCase()}@test.com`; | ||
adminId = await getUserIdFromSignUp(adminEmail); | ||
|
||
const organization = new Organization({ | ||
name: 'tenant organization', | ||
description: 'testing org', | ||
isPublic: true, | ||
visibileInSearch: true, | ||
status: 'ACTIVE', | ||
members: [adminId], | ||
admins: [adminId], | ||
posts: [], | ||
membershipRequests: [], | ||
blockedUsers: [], | ||
groupChats: [], | ||
image: '', | ||
creator: adminId, | ||
}); | ||
const savedOrg = await organization.save(); | ||
organizationId = savedOrg._id; | ||
|
||
const admin = await User.findById(adminId); | ||
admin.overwrite({ | ||
...admin._doc, | ||
joinedOrganizations: [organizationId], | ||
createdOrganizations: [organizationId], | ||
adminFor: [organizationId], | ||
}); | ||
await admin.save(); | ||
|
||
const tenant = new Tenant({ | ||
organization: organizationId, | ||
url: tenantUrl, | ||
}); | ||
await tenant.save(); | ||
}); | ||
|
||
afterAll(async () => { | ||
const conn1 = connectionManager.getTenantConnection(organizationId); | ||
const conn2 = connectionManager.getTenantConnection(secondOrganizationId); | ||
await conn1.Post.deleteMany(); | ||
await conn2.Post.deleteMany(); | ||
await User.findByIdAndDelete(adminId); | ||
await Organization.findByIdAndDelete(organizationId); | ||
await Organization.findByIdAndDelete(secondOrganizationId); | ||
await Tenant.deleteMany({}); | ||
await connectionManager.destroyConnections(); | ||
await database.disconnect(); | ||
}); | ||
|
||
describe('tenant is working and transparent from main db', () => { | ||
test('initTenants and destroyConnections', async () => { | ||
let conn = connectionManager.getTenantConnection(organizationId); | ||
expect(conn).toBe(null); | ||
await connectionManager.initTenants(); | ||
conn = connectionManager.getTenantConnection(organizationId); | ||
expect(conn).toBeTruthy(); | ||
await connectionManager.destroyConnections(); | ||
conn = connectionManager.getTenantConnection(organizationId); | ||
expect(conn).toBe(null); | ||
await connectionManager.initTenants(); | ||
}); | ||
test('addConnection', async () => { | ||
const organization = new Organization({ | ||
name: 'second tenant organization', | ||
description: 'testing org', | ||
isPublic: true, | ||
visibileInSearch: true, | ||
status: 'ACTIVE', | ||
members: [adminId], | ||
admins: [adminId], | ||
posts: [], | ||
membershipRequests: [], | ||
blockedUsers: [], | ||
groupChats: [], | ||
image: '', | ||
creator: adminId, | ||
}); | ||
|
||
const savedOrg = await organization.save(); | ||
secondOrganizationId = savedOrg._id; | ||
|
||
const admin = await User.findById(adminId); | ||
admin.overwrite({ | ||
...admin._doc, | ||
joinedOrganizations: [organizationId, secondOrganizationId], | ||
createdOrganizations: [organizationId, secondOrganizationId], | ||
adminFor: [organizationId, secondOrganizationId], | ||
}); | ||
await admin.save(); | ||
const tenant = new Tenant({ | ||
organization: secondOrganizationId, | ||
url: secondTenantUrl, | ||
}); | ||
await tenant.save(); | ||
|
||
const conn = await connectionManager.addTenantConnection( | ||
secondOrganizationId | ||
); | ||
expect(conn).toBeTruthy(); | ||
const posts = await conn.Post.find(); | ||
expect(posts).toEqual([]); | ||
}); | ||
|
||
test('getConnection', async () => { | ||
const conn = connectionManager.getTenantConnection(organizationId); | ||
const newPost = new conn.Post({ | ||
status: 'ACTIVE', | ||
likedBy: [adminId], | ||
likeCount: 1, | ||
comments: [], | ||
text: 'a', | ||
title: 'a', | ||
imageUrl: 'a.png', | ||
videoUrl: 'a', | ||
creator: adminId, | ||
organization: organizationId, | ||
}); | ||
await newPost.save(); | ||
const [savedPost] = await conn.Post.find(); | ||
expect(savedPost).toBeTruthy(); | ||
}); | ||
|
||
test('Isolated tenants', async () => { | ||
const conn1 = connectionManager.getTenantConnection(organizationId); | ||
const conn2 = connectionManager.getTenantConnection(secondOrganizationId); | ||
|
||
const firstOrgPosts = await conn1.Post.find(); | ||
const secondOrgPosts = await conn2.Post.find(); | ||
|
||
expect(firstOrgPosts).toHaveLength(1); | ||
expect(secondOrgPosts).toHaveLength(0); | ||
}); | ||
}); |