mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-31 10:18:54 +00:00
updated mysql-async
Updated mysql-async
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
root = true
|
||||
|
||||
[**.js]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = null
|
||||
|
||||
[**.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -0,0 +1,4 @@
|
||||
src/node_modules
|
||||
src/package-lock.json
|
||||
|
||||
.idea
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright © 2017, Joel Wurtz; © 2018 Matthias Mandelartz
|
||||
Copyright © 2017, Joel Wurtz; © 2018 - 2019 Matthias Mandelartz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the “Software”), to deal in the Software without restriction, including without limitation the
|
||||
|
||||
+33
-22
@@ -1,13 +1,16 @@
|
||||
# MySQL Async Library for FiveM
|
||||
# mysql-async Library for FiveM
|
||||
|
||||
This library intends to provide function to connect to a MySQL library in a Sync and Async Way.
|
||||
This library intends to provide function to connect to a MySQL library in a Sync and Async way.
|
||||
|
||||
## Disclaimer
|
||||
## Table of Contents
|
||||
* [Installation](#installation)
|
||||
* [Configuration](#configuration)
|
||||
* [keepAlive](#keepalive)
|
||||
* [ConVars](#convars)
|
||||
* [GUI](#gui)
|
||||
* [Usage](#usage)
|
||||
* [Features](#features)
|
||||
|
||||
This mod does not replace EssentialMode, it offers instead a way of connecting to MySQL from lua-scripts, but
|
||||
it will never contain any gameplay logic. It will remain a simple wrapper around MySQL functions.
|
||||
|
||||
All feedback is appreciated in order to deliver a stable release.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -20,19 +23,32 @@ Once installed, you will need to add this line of code in the resource file of e
|
||||
server_script '@mysql-async/lib/MySQL.lua'
|
||||
```
|
||||
|
||||
### Warning
|
||||
|
||||
On Linux servers, users need to stick with the old mysql-async 2.x at least for the moment, due to some issues the linux server has with v8/javascript.
|
||||
|
||||
It can be downloaded from https://github.com/brouznouf/fivem-mysql-async/tree/2.0 or the release section. Note that the connection_string is different for 3.0.0 and 2.x.
|
||||
|
||||
## Configuration
|
||||
|
||||
Add this convar to your server configuration and change the values according to your MySQL installation:
|
||||
|
||||
`set mysql_connection_string "mysql://username:password@host/database?dateStrings=true"`
|
||||
`set mysql_connection_string "server=localhost;uid=mysqluser;password=password;database=fivem"`
|
||||
|
||||
Further options can be found under https://github.com/mysqljs/mysql#connection-options
|
||||
Alternatively an url-like connection string can be used:
|
||||
|
||||
`set mysql_connection_string "mysql://username:password@host/database"`
|
||||
|
||||
Further options can be found under https://github.com/mysqljs/mysql#connection-options for the mysql.js connection string, they can be added on both: the semicolon seperated string or the url-like string.
|
||||
|
||||
### keepAlive
|
||||
|
||||
For people, having issues with the connection being interrupted for usually a bad network configuration, but have no way of figuring out what is wrong, there is an option to enable keep alive queries. This will execute a query on the given interval. To enable those keep alive queries, append e.g. `keepAlive=60` to your connection string, seperated with a semicolon, to ensure that a keep alive query is fired every 60s.
|
||||
|
||||
### ConVars
|
||||
|
||||
The following ConVars are available in the `server.cfg` which you execute. These have also to be set before `start mysql-async`
|
||||
* `set mysql_debug 1`: Prints out the actual consumed query.
|
||||
* `set mysql_debug_output "console"`: Select where to output the log, accepts `console`, `file`, and `both`. In case of `both` and `file` a file named `mysql-async.log` in your main server folder will be created.
|
||||
* `set mysql_slow_query_warning 200`: Sets a limit in ms, queries slower than this limit will be displayed with a warning at the specified location of `mysql_debug_output`, see above.
|
||||
|
||||
## GUI
|
||||
|
||||
Since the newest version, anyone with ace admin rights can open the GUI by typing `mysql` in the F8 console. This opens a profiling view of the data collected by this middleware, that might help you optimize resources and queries. You can disable the viewing of certain data by clicking on the respective entry in the legends, and can browse a table of the 21 slowest performing queries.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -115,12 +131,7 @@ local countPlayer = MySQL.Sync.fetchScalar("SELECT COUNT(1) FROM players")
|
||||
|
||||
## Features
|
||||
|
||||
* Async / Sync
|
||||
* Async / Sync.
|
||||
* It uses the https://github.com/mysqljs/mysql library to provide a connection to your mysql server.
|
||||
* Create and close a connection for each query, the underlying library use a connection pool so only the
|
||||
mysql auth is done each time, old tcp connections are keeped in memory for performance reasons
|
||||
|
||||
## Credits
|
||||
|
||||
Some parts of this library, and also my understanding were directly inspired by "Essential Mode", thanks to
|
||||
them to have begin to work on this, which allows guy like me to not start from scratch every time...
|
||||
mysql auth is done each time, old tcp connections are keeped in memory for performance reasons.
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937'
|
||||
|
||||
version '3.2.0'
|
||||
|
||||
server_script 'mysql-async.js'
|
||||
client_script 'mysql-async-client.js'
|
||||
|
||||
files {
|
||||
'ui/index.html',
|
||||
'ui/app.js',
|
||||
'ui/app.css',
|
||||
'ui/fonts/fira-sans-v9-latin-700.woff',
|
||||
'ui/fonts/fira-sans-v9-latin-700.woff2',
|
||||
'ui/fonts/fira-sans-v9-latin-italic.woff',
|
||||
'ui/fonts/fira-sans-v9-latin-italic.woff2',
|
||||
'ui/fonts/fira-sans-v9-latin-regular.woff',
|
||||
'ui/fonts/fira-sans-v9-latin-regular.woff2',
|
||||
'ui/fonts/MaterialIcons-Regular.eot',
|
||||
'ui/fonts/MaterialIcons-Regular.ttf',
|
||||
'ui/fonts/MaterialIcons-Regular.woff',
|
||||
'ui/fonts/MaterialIcons-Regular.woff2',
|
||||
}
|
||||
|
||||
ui_page 'ui/index.html'
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
let isNuiActive = false;
|
||||
|
||||
function NuiMessage(msg) {
|
||||
window.SendNuiMessage(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
function NuiCallback(name, callback) {
|
||||
window.RegisterNuiCallbackType(name);
|
||||
window.on(`__cfx_nui:${name}`, (data, cb) => {
|
||||
callback(data);
|
||||
cb('ok');
|
||||
});
|
||||
}
|
||||
|
||||
function setNuiActive(boolean = true) {
|
||||
if (boolean !== isNuiActive) {
|
||||
if (boolean) {
|
||||
window.emitNet('mysql-async:request-data');
|
||||
}
|
||||
isNuiActive = boolean;
|
||||
NuiMessage({ type: 'onToggleShow' });
|
||||
window.SetNuiFocus(boolean, boolean);
|
||||
}
|
||||
}
|
||||
|
||||
window.RegisterCommand('mysql', () => {
|
||||
setNuiActive();
|
||||
}, true);
|
||||
|
||||
NuiCallback('close-explorer', () => {
|
||||
setNuiActive(false);
|
||||
});
|
||||
|
||||
window.setInterval(() => {
|
||||
if (isNuiActive) {
|
||||
window.emitNet('mysql-async:request-data');
|
||||
}
|
||||
}, 300000);
|
||||
|
||||
window.onNet('mysql-async:update-resource-data', (resourceData) => {
|
||||
let arrayToSortAndMap = [];
|
||||
const resources = Object.keys(resourceData);
|
||||
for (let i = 0; i < resources.length; i += 1) {
|
||||
if (Object.prototype.hasOwnProperty.call(resourceData, resources[i])) {
|
||||
if (Object.prototype.hasOwnProperty.call(resourceData[resources[i]], 'totalExecutionTime')) {
|
||||
arrayToSortAndMap.push({
|
||||
resource: resources[i],
|
||||
queryTime: resourceData[resources[i]].totalExecutionTime,
|
||||
count: resourceData[resources[i]].queryCount,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (arrayToSortAndMap.length > 0) {
|
||||
arrayToSortAndMap.sort((a, b) => a.queryTime - b.queryTime);
|
||||
const len = arrayToSortAndMap.length;
|
||||
arrayToSortAndMap = arrayToSortAndMap.filter((_, index) => index > len - 31);
|
||||
arrayToSortAndMap.sort((a, b) => {
|
||||
const resourceA = a.resource.toLowerCase();
|
||||
const resourceB = b.resource.toLowerCase();
|
||||
let result = 0;
|
||||
if (resourceA < resourceB) {
|
||||
result = -1;
|
||||
} else if (resourceA > resourceB) {
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
NuiMessage({
|
||||
type: 'onResourceLabels',
|
||||
resourceLabels: arrayToSortAndMap.map(el => el.resource),
|
||||
});
|
||||
NuiMessage({
|
||||
type: 'onResourceData',
|
||||
resourceData: [
|
||||
{
|
||||
data: arrayToSortAndMap.map(el => el.queryTime),
|
||||
},
|
||||
{
|
||||
data: arrayToSortAndMap.map(el => ((el.count > 0) ? el.queryTime / el.count : 0)),
|
||||
},
|
||||
{
|
||||
data: arrayToSortAndMap.map(el => el.count),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.onNet('mysql-async:update-time-data', (timeData) => {
|
||||
let timeArray = [];
|
||||
if (Array.isArray(timeData)) {
|
||||
const len = timeData.length;
|
||||
timeArray = timeData.filter((_, index) => index > len - 31);
|
||||
}
|
||||
if (timeArray.length > 0) {
|
||||
NuiMessage({
|
||||
type: 'onTimeData',
|
||||
timeData: [
|
||||
{
|
||||
data: timeArray.map(el => el.totalExecutionTime),
|
||||
},
|
||||
{
|
||||
data: timeArray.map(el => ((el.queryCount > 0) ? el.totalExecutionTime / el.queryCount
|
||||
: 0)),
|
||||
},
|
||||
{
|
||||
data: timeArray.map(el => el.queryCount),
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.onNet('mysql-async:update-slow-queries', (slowQueryData) => {
|
||||
const slowQueries = slowQueryData.map((el) => {
|
||||
const element = el;
|
||||
element.queryTime = Math.round(el.queryTime * 100) / 100;
|
||||
return element;
|
||||
});
|
||||
NuiMessage({
|
||||
type: 'onSlowQueryData',
|
||||
slowQueries,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
+921
-922
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user