sequelizejs saving an object when row was removed - javascript

I have the following code. The idea is that I update a database row in an interval, however if I remove the row manually from the database while this script runs, the save() still goes into success(), but the row is not actually put back into the database. (Because sequelize does an update query with a where clause and no rows match.) I expected a new row to be created or error() to be called. Any ideas to what I can do to make this behave like I want to?
var Sequelize = require("sequelize")
, sequelize = new Sequelize('test', 'test', 'test', {logging: false, host: 'localhost'})
, Server = sequelize.import(__dirname + "/models/Servers")
sequelize.sync({force: true}).on('success', function() {
Server
.create({ hostname: 'Sequelize Server 1', ip: '127.0.0.1', port: 0})
.on('success', function(server) {
console.log('Server added to db, going to interval');
setInterval(function() { console.log('timeout reached'); server.port = server.port + 1; server.save().success(function() { console.log('saved ' + server.port) }).error(function(error) { console.log(error); }); }, 1000);
})
})

I'm afraid what you are trying to do is not currently supported by sequelize.
Error callbacks are only ment for actual error situations, i.e. SQL syntax errors, stuff like that. Trying to update a non-existing row is not an error in SQL.
The import distinction here is, that you are modifying your database outside of your program. Sequelize has no way of knowing that! I have two possible solutions, only one of which is viable right now:
1 (works right now)
Use sequelize.query to include error handling in your query
IF EXISTS (SELELCT * FROM table WHERE id = 42)
UPDATE table SET port = newport WHERE id = 42
ELSE
INSERT INTO table ... port = newport
Alternatively you could create a feature request on the sequelize github for INSERT ... ON DUPLICATE KEY UPDATE syntax to be implemented see and here
2 (will work when transactions are implemented
Use transactions to first check if the row exists, and insert it if it does not. Transactions are on the roadmap for sequelize, but not currently supported. If you are NOT using connection pooling, you might be able to acomplish transactions manually by calling sequelize.query('BEGIN / COMMIT TRANSACTION').

Related

Connection already made to a IndexedDB Database after call in Dexie

When I try to call Dexie on a database on which another call has been done by IndexedDB, there rises an error that the connection is already made to the database.
Can we pass an existing connection to Indexedb to Dexie?
This can be helpful when we want to use same connection in a Dexie object and another object and this happens to me when I try to add Dexie to my project. I don't want to rewrite the existing function.
Example:
function initDataBase(callback){
if(window.indexedDB){
var requeteBDD = window.indexedDB.open("databasename",1);
requeteBDD.onsuccess = function(){
if(typeof callback == "function")
callback(requeteBDD.result);
};
}
}
So can we do,for instance
initDataBase(function(db){
var dex = new Dexie(db);
});
I would like to use same connection as the first one.
Is it possible?
It's not possible as of current version to pass an instance of IDBDatabase into Dexie constructor. However, this would definitely be an easy pull request to do in the source, as Dexie already has the ability to open existing database by name and adapt to it's existing schema.
However, you should not get an error if you instanciate multiple IDBDatabases to same database name unless one of them tries to upgrade it using another version.
Dexie can open an existing database without creating the schema (even though you can only pass a name and not the db instance), as shown in the following fiddle: https://jsfiddle.net/dfahlander/b8Levamm/
new Dexie('MyDatabase').open().then(function (db) {
log ("Found database: " + db.name);
log ("Database version: " + db.verno);
db.tables.forEach(function (table) {
log ("Found table: " + table.name);
log ("Table Schema: " +
JSON.stringify(table.schema, null, 4));
});
}).catch('NoSuchDatabaseError', function(e) {
// Database with that name did not exist
log ("Database not found");
}).catch(function (e) {
log ("Oh uh: " + e);
});
(which fails because the given DB is not there. But if you create it on jsfiddle and run it again, you'll see it open).

Is it safe to use a single Mongoose database from two files/processes?

I've been working on a server and a push notification daemon that will both run simultaneously and interact with the same database. The idea behind this is that if one goes down, the other will still function.
I normally use Swift but for this project I'm writing it in Node, using Mongoose as my database. I've created a helper class that I import in both my server.js file and my notifier.js file.
const Mongoose = require('mongoose');
const Device = require('./device'); // This is a Schema
var uri = 'mongodb://localhost/devices';
function Database() {
Mongoose.connect(uri, { useMongoClient: true }, function(err) {
console.log('connected: ' + err);
});
}
Database.prototype.findDevice = function(params, callback) {
Device.findOne(params, function(err, device) {
// etc...
});
};
module.exports = Database;
Then separately from both server.js and notifier.js I create objects and query the database:
const Database = require('./db');
const db = new Database();
db.findDevice(params, function(err, device) {
// Simplified, but I edit and save things back to the database via db
device.token = 'blah';
device.save();
});
Is this safe to do? When working with Swift (and Objective-C) I'm always concerned about making things thread safe. Is this a concern? Should I be worried about race conditions and modifying the same files at the same time?
Also, bonus question: How does Mongoose share a connection between files (or processes?). For example Mongoose.connection.readyState returns the same thing from different files.
The short answer is "safe enough."
The long answer has to do with understanding what sort of consistency guarantees your system needs, how you've configured MongoDB, and whether there's any sharding or replication going on.
For the latter, you'll want to read about atomicity and consistency and perhaps also peek at write concern.
A good way to answer these questions, even when you think you've figured it out, is to test scenarios: Hammer a duplicate of your system with fake data and events and see if what happen is OK or not.

Using mysql node.js driver to get an entire database as JSON

I'm working on creating a JavaScript file to get a JSON dump of an entire MySQL database, running on server side. I found and am using the MySQL driver for node.js (https://www.npmjs.com/package/mysql) for queries, it's been straight forward enough to start. My issue is that I need to call multiple queries and get the results from all of them to put into a single JSON file and I can't quite get that to work. I'm entirely new to JavaScript (basically never touched it before now) so it's probably a relatively simple solution that I'm just missing.
Currently I do a query of 'SHOW TABLES' to get a list of all the tables (this can change so I can't just assume a constant list). I then just want to basically loop through the list and call 'SELECT * from table_name' for each table, combining the results as I go to get one big JSON. Unfortunately I haven't figured out how to get the code to finish all the queries before trying to combine them, thus retuning 'undefined' for all the results. Here is what I currently have:
var mysql = require('mysql');
var fs = require('fs');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'pass',
database: 'test_data'
});
connection.connect();
connection.query('SHOW TABLES;', function(err, results, fields)
{
if(err) throw err;
var name = fields[0].name;
var database_json = get_table(results[0][name]);
for (i = 1; i < results.length; i++)
{
var table_name = results[i][name];
var table_json = get_table(table_name);
database_json = database_table_json.concat(table_json);
}
fs.writeFile('test_data.json', JSON.stringify(database_json), function (err)
{
if (err) throw err;
});
connection.end();
});
function get_table(table_name)
{
connection.query('select * from ' + table_name + ';', function(err, results, fields) {
if(err) throw err;
return results;
});
}
This gets the table list and goes through all of it with no issue, and the information returned by the second query is correct if I just do a console.log(results) inside the query, but the for loop just keeps going before any query is completed and thus 'table_json' just ends up being 'undefined'. I really think this must be an easy solution (probably something with callbacks which I don't quite understand fully yet) but I keep stumbling.
Thanks for the help.
I'm guessing that this is for some sort of maintenance type function and not a piece that you need for your application. You're probably safe to do this asynchronously. This module is available here: https://github.com/caolan/async
You can also use Q promises, available here: https://github.com/kriskowal/q
This answer: describes both approaches pretty well: Simplest way to wait some asynchronous tasks complete, in Javascript?

CloudCode multiple query in query doesn't work

I'm trying to find users I didn't connect to before with a cloud function. There are few tables I'm using:
Users table - The standard table with an added "hasLight" boolean column
Connected table:
'user' - pointer to the user (first side)
'userId' - objectId of the user
'user2' - pointer to the user we connect with
'userId2' - objectId of the user we connected to
Available table:
'userObjectId' - objectId of the user
'counter' - number
The code:
Parse.Cloud.define("findFreshUser", function(request, response) {
Parse.Cloud.useMasterKey(); // For reading all the table //
var user = Parse.User.current();
// Get all possible users we already connected to //
var connectQuery = new Parse.Query("Connected");
connectQuery.include('userId2');
connectQuery.equalTo("userId", Parse.User.current().id);
// Get all users with availability of '0' //
var availableQuery = new Parse.Query("Available");
availableQuery.notEqualTo("counter", 0);
var freshUserQuery = new Parse.Query(Parse.User);
freshUserQuery.doesNotMatchKeyInQuery("objectId", "userId2", connectQuery); // We haven't connected before - THIS DOEN'T WORK !!! //
freshUserQuery.doesNotMatchKeyInQuery("objectId", "userObjectId", availableQuery); // We won't use '0' availability users - THIS WORKS //
freshUserQuery.equalTo("hasLight", false); // user must not have a light //
freshUserQuery.descending("updatedAt");
freshUserQuery.limit(1); // We need only 1 user //
freshUserQuery.find({
success: function(results) {
if (results.length>0){
console.log("Found the user "+ results[0].id);
response.success(results[0].id);
}else{
response.error("No user found");
}
},
error: function() {
response.error("No user found");
}
});
});
For some reason CloudCode completely ignoring connectQuery (all other statements are fine) when using 2 doesNotMatchKeyInQuery statements:
When using only
freshUserQuery.doesNotMatchKeyInQuery("objectId", "userId2", connectQuery);
and comment out
freshUserQuery.doesNotMatchKeyInQuery("objectId", "userObjectId", availableQuery);
it does work. So I think it is related to using both at same time, they are probably conflicting each other. What do I need to do to make both apply?
It feels like it's some parse issue but I'm really new to CloudCode so it's probably something I'm not doing right.
Note: Pay attention that I even don't compare the user object itself but the id of it (this is as part of isolating the issue). Means, I know I could make the code and DB lots nicer.
You have to use Promise to achieve such query : blog.parse.com/learn/engineering/whats-so-great-about-javascript-promises/

MongoDB / Express - How to switch database after connecting via connect()

I am using express to connect to my mongoDB:
mongodb.MongoClient.connect(mongourl, function(err, database) {
// How would one switch to another database here?
});
I have to connect to the admin database in the first place. After the conenction has been established, i would like to switch the database.
Although i have searched through the official documentation, i was unable to find something that fits my needs.
I am aware of the MongoClient::open() method, but i would like to stick to connect().
Any help is appreciated.
You can switch to another database like so:
mongodb.MongoClient.connect(mongourl, function(err, database) {
// switch to another database
database = database.db(DATABASE_NAME);
...
});
(docs)
EDIT: for clarification: this also allows you to open multiple databases over the same connection:
mongodb.MongoClient.connect(mongourl, function(err, database) {
// open another database over the same connection
var database2 = database.db(DATABASE_NAME);
// now you can use both `database` and `database2`
...
});
You just have to call MongoClient.connect once again, because there is one connection per database. That means, you cannot change the database of an existing connection. You have to connect a second time:
mongodb.MongoClient.connect(mongourl, function(err, database) {
mongodb.MongoClient.connect(mongourl_to_other_database, function(err, database2) {
// use database or database2
});
});

Categories