Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions database/ignite/ignite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const IgniteClient = require("apache-ignite-client");
const logger = require("./../../lib/log")(__filename);
const { SqlFieldsQuery } = require("apache-ignite-client/lib/Query");
const IgniteClientConfiguration = IgniteClient.IgniteClientConfiguration;
const CacheConfiguration = IgniteClient.CacheConfiguration;
require("dotenv").config();
const igniteModule = {};
let igniteClient;
igniteModule.startIgnite = async () => {
try {
igniteClient = new IgniteClient();
const configuration = new IgniteClientConfiguration(process.env.IGNITE_HOST)
.setUserName(process.env.IGNITE_USER)
.setPassword(process.env.IGNITE_PASSWORD);
await igniteClient.connect(configuration);
logger.info("Connected to Ignite database");
} catch (err) {
logger.error(err);
throw new Error(err);
}
};
igniteModule.checkAccount = async (username) => {
if (!username) return;
try {
const caches = await igniteClient.cacheNames();
return caches.includes(username);
} catch (err) {
logger.error(`Error checking ignite database for ${username}`);
throw new Error(err);
}
};
igniteModule.closeIgnite = async () => {
try {
await igniteClient.disconnect();
logger.info("Closed connection to Ignite database");
} catch (err) {
logger.error(`Error closing connection to Ignite database`);
throw new Error(err);
}
};

igniteModule.createAccount = async (user) => {
const { username, dbPassword } = user;
if (!username || !dbPassword) return;
try {
const cache = await igniteClient.getOrCreateCache(
username,
new CacheConfiguration().setSqlSchema("PUBLIC")
);
await cache.query(
new SqlFieldsQuery(
`CREATE USER "${username}" WITH PASSWORD '${dbPassword}'`
)
);
logger.info(`Successfully created ${username} cache`);
} catch (err) {
logger.error(`Error creating ignite ${username}`);
throw new Error(err);
}
};
igniteModule.deleteAccount = async (username) => {
if (!username) return;
try {
const cache = await igniteClient.getOrCreateCache(
username,
new CacheConfiguration().setSqlSchema("PUBLIC")
);
await cache.query(new SqlFieldsQuery(`DROP USER "${username}"`));
await igniteClient.destroyCache(username);
logger.info(`Successfully deleted ${username} cache`);
} catch (err) {
logger.error(`Error deleting ignite ${username}`);
throw new Error(err);
}
};
module.exports = igniteModule;
110 changes: 110 additions & 0 deletions database/ignite/ignite.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
jest.mock("apache-ignite-client");
jest.mock("../../lib/log");
const logGen = require("../../lib/log");
const logger = {
info: jest.fn(),
error: jest.fn(),
};
logGen.mockReturnValue(logger);
require("dotenv").config();
const {
startIgnite,
createAccount,
deleteAccount,
checkAccount,
closeIgnite,
} = require("./ignite");

const IgniteClient = require("apache-ignite-client");
const mockClient = {
cacheNames: jest.fn(),
connect: jest.fn(),
disconnect: jest.fn(),
getOrCreateCache: jest.fn().mockReturnThis(),
query: jest.fn(),
destroyCache: jest.fn(),
};
IgniteClient.mockImplementation(() => mockClient);
const mockConfig = {
setUserName: jest.fn().mockReturnThis(),
setPassword: jest.fn().mockReturnThis(),
};
IgniteClient.IgniteClientConfiguration.mockImplementation(() => mockConfig);
describe("IgniteDb functions", () => {
beforeEach(() => {
jest.clearAllMocks();
});
const user = { username: "username", dbPassword: "password" };
it("should start Ignite client", () => {
startIgnite();
expect(IgniteClient).toHaveBeenCalledTimes(1);
expect(mockClient.connect).toHaveBeenCalledTimes(1);
expect(IgniteClient.IgniteClientConfiguration).toHaveBeenCalledTimes(1);
expect(mockConfig.setUserName.mock.calls[0][0]).toEqual("ignite");
expect(mockConfig.setPassword.mock.calls[0][0]).toEqual("ignite");
});
it("should throw an error if starting client goes wrong", async () => {
try {
mockClient.connect.mockReturnValue(Promise.reject());
expect(await startIgnite()).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should close ignite client", () => {
closeIgnite();
expect(mockClient.disconnect).toHaveBeenCalledTimes(1);
});
it("should call logger error if closing client goes wrong", async () => {
try {
mockClient.disconnect.mockReturnValue(Promise.reject());
await closeIgnite();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should check for existsting accounts", async () => {
mockClient.cacheNames.mockReturnValue(["testName", "", "username"]);
const result = await checkAccount(user.username);
expect(mockClient.cacheNames).toHaveBeenCalledTimes(1);
expect(result).toEqual(true);
});
it("should call logger error if checking for account goes wrong", async () => {
try {
mockClient.cacheNames.mockReturnValue(Promise.reject());
await checkAccount(user.username);
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should create new account", async () => {
await createAccount(user);
expect(mockClient.getOrCreateCache.mock.calls[0][0]).toEqual(user.username);
});
it("should delete user", async () => {
await deleteAccount(user.username);
expect(mockClient.getOrCreateCache.mock.calls[0][0]).toEqual(user.username);
expect(mockClient.destroyCache.mock.calls[0][0]).toEqual(user.username);
});
it("should call logger error if creating a user goes wrong", async () => {
try {
mockClient.getOrCreateCache.mockReturnValue(Promise.reject());
expect(await createAccount(user)).rejects.toThrow();
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
it("should return undefined if no arguments were provided", async () => {
expect(await createAccount({})).toEqual(undefined);
expect(await checkAccount("")).toEqual(undefined);
expect(await deleteAccount("")).toEqual(undefined);
});
it("should calll logger error if deleting user goes wrong", async () => {
try {
mockClient.getOrCreateCache.mockReturnValue(Promise.reject());
await deleteAccount(user.username);
} catch (err) {
expect(logger.error).toHaveBeenCalledTimes(1);
}
});
});
22 changes: 22 additions & 0 deletions database/ignite/igniteConfig.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="dataStorageConfiguration">
<bean class="org.apache.ignite.configuration.DataStorageConfiguration">
<property name="defaultDataRegionConfiguration">
<bean class="org.apache.ignite.configuration.DataRegionConfiguration">
<property name="maxSize" value="#{200 * 1024 * 1024}"/>
<property name="persistenceEnabled" value="true"/>
</bean>
</property>
</bean>
</property>

<property name="authenticationEnabled" value="true"/>

</bean>
</beans>
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const {startServer} = require('./src/server')
const { startServer } = require("./src/server");

startServer(process.env.PORT || 3052)
startServer(process.env.PORT || 3052);
72 changes: 35 additions & 37 deletions lib/log.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,40 @@
const {createLogger, format, transports} = require('winston')
const util = require('util')
const { createLogger, format, transports } = require("winston");
const util = require("util");

module.exports = (file) => {
const logger = createLogger({
format: format.combine(
format.timestamp({format:'YYYY-MM-DD HH:mm:ss'}),
format.label({
label: file.split(/(\\|\/)/g).pop()
}),
format.colorize(),
format.printf((info) => {
return `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`
})
),
transports : [
new transports.Console()
]
})
const logger = createLogger({
format: format.combine(
format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
format.label({
label: file.split(/(\\|\/)/g).pop(),
}),
format.colorize(),
format.printf((info) => {
return `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`;
})
),
transports: [new transports.Console()],
});

const processArgs = (args) => {
const mappedArgs = args.map((e) => {
if (e instanceof Error) return e.toString()
return e
})
return util.format('%j', mappedArgs)
}
const processArgs = (args) => {
const mappedArgs = args.map((e) => {
if (e instanceof Error) return e.toString();
return e;
});
return util.format("%j", mappedArgs);
};

const obj = {
info: (...args) => {
logger.info(processArgs(args))
},
warn: (...args) => {
logger.warn(processArgs(args))
},
error: (...args) => {
logger.error(processArgs(args))
}
}
const obj = {
info: (...args) => {
logger.info(processArgs(args));
},
warn: (...args) => {
logger.warn(processArgs(args));
},
error: (...args) => {
logger.error(processArgs(args));
},
};

return obj
}
return obj;
};
82 changes: 42 additions & 40 deletions lib/log.test.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,48 @@
const winston = require('winston')
const util = require('util')
const winston = require("winston");
const util = require("util");

winston.createLogger = jest.fn().mockReturnValue({
info: () => {},
warn: () => {},
error: () => {}
})
info: () => {},
warn: () => {},
error: () => {},
});

winston.format = {
combine: () => {},
timestamp: () => {},
label: () => {},
colorize: () => {},
printf: jest.fn()
}
combine: () => {},
timestamp: () => {},
label: () => {},
colorize: () => {},
printf: jest.fn(),
};

util.format = jest.fn()
util.format = jest.fn();

describe('Testing log.js', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('should call util.format everytime when log.xxx is called', () => {
const logger = require('./log')(__filename)
logger.info('message', [0,1,2])
logger.warn('message', {obj: () => {}})
logger.error('message', new Error('error message'))
expect(util.format).toHaveBeenCalled()
})
it('should call winston.createLogger when log is required', () => {
const logger = require('./log')(__filename)
expect(winston.createLogger).toHaveBeenCalled()
})
it('should return log string correctly', () => {
const logger = require('./log')(__filename)
const argInPrintf = winston.format.printf.mock.calls[0][0]
const testData = {
timestamp: "2020-04-30 22:43:00",
level: "info",
label: "log.test.js",
message: "message"
}
expect(argInPrintf(testData)).toBe("2020-04-30 22:43:00 info [log.test.js]: message")
})
})
describe("Testing log.js", () => {
beforeEach(() => {
jest.clearAllMocks();
});
it("should call util.format everytime when log.xxx is called", () => {
const logger = require("./log")(__filename);
logger.info("message", [0, 1, 2]);
logger.warn("message", { obj: () => {} });
logger.error("message", new Error("error message"));
expect(util.format).toHaveBeenCalled();
});
it("should call winston.createLogger when log is required", () => {
const logger = require("./log")(__filename);
expect(winston.createLogger).toHaveBeenCalled();
});
it("should return log string correctly", () => {
const logger = require("./log")(__filename);
const argInPrintf = winston.format.printf.mock.calls[0][0];
const testData = {
timestamp: "2020-04-30 22:43:00",
level: "info",
label: "log.test.js",
message: "message",
};
expect(argInPrintf(testData)).toBe(
"2020-04-30 22:43:00 info [log.test.js]: message"
);
});
});
Loading