Skip to content

Commit

Permalink
refactor: Transaction tweaks and version bump 1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dunak-debug committed Sep 20, 2021
1 parent faae020 commit 372a956
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 45 deletions.
2 changes: 1 addition & 1 deletion fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ game 'common'

name 'oxmysql'
description 'Database wrapper for FiveM utilising node-mysql2 offering improved performance and security.'
version '1.3.5'
version '1.4.0'
url 'https://github.com/overextended/oxmysql'
author 'overextended'
use_fxv2_oal 'yes'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "oxmysql",
"version": "1.3.5",
"version": "1.4.0",
"main": "oxmysql.js",
"description": "FiveM MySQL wrapper using faster mysql2",
"repository": "[email protected]:overextended/oxmysql.git",
Expand Down
31 changes: 14 additions & 17 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,20 @@ if (Object.keys(config).length === 0)
const slowQueryWarning = GetConvarInt('mysql_slow_query_warning', 100);
const debug = GetConvar('mysql_debug', 'false') === 'true';

let isolationLevel;
switch (GetConvarInt('mysql_transaction_isolation_level', 2)) {
case 1:
isolationLevel = 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ';
break;
case 2:
isolationLevel = 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED';
break;
case 3:
isolationLevel = 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED';
break;
case 4:
isolationLevel = 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE';
break;
default:
break;
};
const isolationLevel = (() => {
switch (GetConvarInt('mysql_transaction_isolation_level', 2)) {
case 1:
return 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ';
case 2:
return 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED';
case 3:
return 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED';
case 4:
return 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE';
default:
return 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED';
};
})();

const resourceName = GetCurrentResourceName() || 'oxmysql';

Expand Down
4 changes: 1 addition & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ global.exports('scalar', (query, parameters, cb, resource = GetInvokingResource(

global.exports('transaction', (queries, parameters, cb, resource = GetInvokingResource()) => {
transaction(queries, parameters, resource).then((result) => {
if (typeof parameters === 'function')
cb = parameters;
safeCallback(cb, result, resource, queries);
safeCallback(cb || parameters, result || false, resource, debug && JSON.stringify(queries));
});
});

Expand Down
29 changes: 14 additions & 15 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const parseTypes = (field, next) => {
const parseParameters = (query, parameters) => {
if (query === undefined) throw new FormatError(`Undefined query passed`);

if(typeof parameters === 'function') return [query, []];
if (typeof parameters === 'function') return [query, []];

if (query.includes('@') || query.includes(':')) return [query, parameters];

Expand All @@ -41,32 +41,31 @@ const parseParameters = (query, parameters) => {

if (Array.isArray(parameters)) {
if (parameters.length !== queryParams.length)
throw new Error(`Undefined array parameter #${parameters.length}`, query, parameters);
throw new Error(`Undefined array parameter #${parameters.length + 1}`, query, parameters);
} else {
queryParams.forEach((_, i) => {
if (parameters[`${i + 1}`] === undefined) throw new FormatError(`Undefined object parameter #${i + 1}`, query, parameters);
if (parameters[`${i + 1}`] === undefined)
throw new FormatError(`Undefined object parameter #${i + 1}`, query, parameters);
});
}

return [query, parameters];
};

const parseParametersTransaction = (queries, parameters) => {
const parseTransaction = (queries, parameters) => {
//https://github.com/GHMatti/ghmattimysql/blob/37f1d2ae5c53f91782d168fe81fba80512d3c46d/packages/ghmattimysql/src/server/utility/sanitizeTransactionInput.ts#L5

const cleanedTransactions = queries.map( (query) => {
let params;

if (typeof query === 'string') {
[query, params] = parseParameters(query, parameters || []);
return { query: query, params: params };
}
if (!Array.isArray(queries)) throw new Error(`Transaction queries must be array type`);

[query, params] = parseParameters(query.query, query.parameters || query.values || []);
return { query: query, params: params };
const parsedTransaction = queries.map((query) => {
const [parsedQuery, parsedParameters] = parseParameters(
typeof query === 'object' ? query.query : query,
(typeof query === 'object' && (query.parameters || query.values)) || parameters || []
);
return { query: parsedQuery, params: parsedParameters };
});

return cleanedTransactions;
return parsedTransaction;
};

export { parseParameters, parseTypes, parseParametersTransaction };
export { parseTypes, parseParameters, parseTransaction };
24 changes: 16 additions & 8 deletions src/transaction.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
import { pool } from './pool';
import { parseParametersTransaction } from './parser';
import { parseTransaction } from './parser';
import { slowQueryWarning, debug, resourceName } from './config';

const transactionError = (queries, parameters) =>
`${queries
.map((query) =>
typeof query === 'string' ? query : `${query.query} ${JSON.stringify(query.values || query.parameters || [])}`
)
.join('\n')}\n${JSON.stringify(parameters)}`;

const transaction = async (queries, parameters, resource) => {
ScheduleResourceTick(resourceName);
const connection = await pool.getConnection();
try {
const time = debug ? process.hrtime.bigint() : Date.now();

const fullQuery = parseParametersTransaction(queries, parameters);
const fullQuery = parseTransaction(queries, parameters);
const transactionAmount = fullQuery.length;

await connection.beginTransaction();

for (let i = 0; i < transactionAmount; i++) {
await connection.query(fullQuery[i].query, fullQuery[i].params);
};
}

await connection.commit();

const executionTime = debug ? Number(process.hrtime.bigint() - time) / 1e6 : Date.now() - time;

if (executionTime >= slowQueryWarning * transactionAmount || debug)
console.log(
`^3[${debug ? 'DEBUG' : 'WARNING'}] ${resource} took ${executionTime}ms to execute a transaction!
${queries} ${JSON.stringify(parameters)}^0`
`^3[${
debug ? 'DEBUG' : 'WARNING'
}] ${resource} took ${executionTime}ms to execute a transaction!\n${transactionError(queries, parameters)}^0`
);

return true;
Expand All @@ -33,12 +41,12 @@ const transaction = async (queries, parameters, resource) => {
console.log(
`^1[ERROR] ${resource} was unable to execute a transaction!
${error.message}
${error.sql || `${queries} ${JSON.stringify(parameters)}`}^0`
${error.sql || `${transactionError(queries, parameters)}`}^0`
);
debug && console.trace(error);
} finally {
connection.release();
}
}
};

export { transaction };
export { transaction };

0 comments on commit 372a956

Please sign in to comment.