Do sequelize promises await postgres trigger completion before they resolve? - javascript

I have a contact postgres table, with a contacted_date column. I recently created a contact_date table, which is meant to store each date a contact was contacted.
Because the codebase frequently refers to the contact table for the most recent contacted date, I haven't migrated all the data out of that table. Instead, contact_date contains each date a given contact was contacted, and a trigger on that table updates contact with the latest date for each contact.
If I use Sequelize to make a change to contact_date, does the promise await the successful completion of the trigger? Or does it only await the successful completion of the change to contact_date?
In most of my code, this isn't a big concern - if I persist a new contact date, then my code already has access to that date, and I can use that date in other calculations if I need it. But I'm running into difficulties with my tests, and it may be because of a race condition. In my tests, I'm creating new contacts with contact dates, and some of my tests are failing, perhaps because the promise is resolving before the trigger has finished doing its work.
Update: This SO post indicates that the trigger is part of the same transaction, implying that the Sequelize promise wouldn't resolve until the trigger had completed, but if someone knows for sure, I'd still like to hear dis/confirmation.

I hope you're using transactions for your queries, without which I feel this would not be possible.
Also, an alternative way to achieve your objective would be to use hooks (basically a trigger at application level) in sequelize, instead of creating trigger at DB level.
Since you can pass the transaction object to hooks, the operation performed under hooks is guaranteed to be part of the same transaction which caused the hook to run.

Related

Detecting changes on database table column status

I am having a project in Laravel. In database I have a status column, which shows if exam is started or not. I had an idea in the waiting room checking every single second if the status was changed or not, if changed to 1, when the exam starts, but I am so new to Laravel and everything else, that I even don't get the main idea how I could do this, I don't ask for any code, just for the lead, to move on. yeah, hope someones gets me. Thanks if someone answers me.
Check about laravel cron jobs. You will need a class implementing ShouldQueue interface and using Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
With regards to the storage of the jobs i do recommend Redis or SQS.
In order to keep monitoring the queue in production think about installing supervisor.
Further information here: Queues
Your plan can work, it is called polling.
Basically, you will want to call
setInterval(function() {
//your code here
}, 1000);
setInterval is a function that receives two parameter. The first is a callback function, that will periodically be executed and the second is the length of the period in milliseconds (1000 milliseconds is a second).
Now, you will need to implement your callback function (Javascript, of course) to send an AJAX request to a Laravel action. You will need to look into XMLHttpRequest and its usages, or you can use some libraries to simplify your task, like jQuery or Axios.
On Laravel's side you will need to implement an action and a Route for it. (read this: https://appdividend.com/2022/01/22/laravel-ajax/)
Your Laravel will need to load data from your database, you can use Eloquent for this purpose or raw queries and then respond the POST request with the result.
Now, in your Javascript at the AJAX request's code you will need to have a callback function (yes, a callback inside a callback) which will handle the response and the the changes.
What about leveraging Observers? Also instead of having a status boolean, you could take a similar approach that Laravel has done for soft deletes and set exam_started_at. This way you can also keep track of time stamp and state all in one column. Also, observers are immediate rather than pushing them into a queue. Then generate a websocket event that can report back to your front end, if needed.
check out Laravel observer and soft delete documentation.
I know you specified "when the column on db changes..." but if it's not a strict-requirement you might want to consider implementing event-based architecture. Laravel has support for model events, which essentially allows you to run certain assertions and controls when a model created, updated, deleted etc.
class Exam extends Model
protected static function booted()
{
static::updated(function ($exam) {
if($exam->status=='your-desired-status'){
//your actions
}
//you can even in cooperate change controls
if ($exam->isDirty('status')){
//means status column changed
});
}
}
Of course this solution applies only if Database in question is in Laravel's reach. If database data changes outside the Laravel application these event listeners won't help at all.

Cloud Functions and Firestore: Using Promise.all() to track multiple documetn modifications

I use a callable Cloud function for creating a new user. For this user, multiple documents in Cloud Firestore are created.
I do not want to store only parts of the data, if one promise (document creation fails), but completely undo the registration, so I use Promise.all(documentCreationPromisses)
So my question is if it is still possible that some documents are created and others are not, although I use Promise.all() ?
Promise.all() returns a promise that tells you if all of the other promises succeeded, or if any one of them failed. It can certainly resolve with a partial set of successes, and there was a failure, you would have to check each individual promise to find out which ones succeeded or failed.
If you are modifying a bunch of documents in Firestore, and you require that all of the modifications either fully succeed, otherwise nothing happens (a full rollback), then you should use a batch write or transaction. With a batch writes and transactions, everything must succeed, or the entire batch fails. The single returned promise from that batch will tell you what happened.

How do Meteor.subscribe and MyCollection.find* operations interact?

I've been following lots of meteor examples and working through discover meteor, and now I'm left with lots of questions. I understand subscribe and fetch are ways to get "reactivity" to work properly, but I still feel unsure about the relationship between find operations and subscriptions/fetch. I'll try to ask some questions in order to probe for some holistic/conceptual answers.
Question Set 1:
In the following example we are fetching 1 object and we are subscribing to changes on it:
Meteor.subscribe('mycollection', someID);
Mycollection.findOne(someID);
Does order of operations matter here?
When does this subscription "expire"?
Question Set 2:
In some cases we want to foreign key lookup and use fetch like this:
MyCollection2.find({myCollection1Id: doc1Id}).fetch();
Do we need also need a MyColletion2.subscribe when using fetch?
How does subscribe work with "foreign keys"?
Is fetch ~= to a subscription?
Question Set 3:
What is an appropriate use of Tracker.autorun?
Why/when should I use it instead of subscribe or fetch?
what happens when you subscribe and find/fetch
The client calls subscribe which informs the server that the client wants to see a particular set of documents.
The server accepts or rejects the subscription request and publishes the matching set of documents.
Sometime later (after network delay) the documents arrive on the client. They are stored in a database in the browser called minimongo.
A subsequent fetch/find on the collection in which the aforementioned documents are stored will query minimongo (not the server).
If the subscribed document set changes, the server will publish a new copy to the client.
Recommended reading: understanding meteor publications and subscriptions.
question 1
The order matters. You can't see documents that you haven't subscribed for (assuming autopublish is off). However, as I point out in common mistakes, subscriptions don't block. So a subscription followed by an immediate fetch is should return undefined.
Subscriptions don't stop on their own. Here's the breakdown:
A global subscription (one made outside of your router or template) will never stop until you call its stop method.
A route subscription (iron router) will stop when the route changes (with a few caveats).
A template subscription will stop when the template is destroyed.
question 2
This should be mostly explained by the first section of my answer. You'll need both sets of documents in order to join them on the client. You may publish both sets at once from the server, or individually - this is a complex topic and depends on your use case.
question 3
These two are somewhat orthogonal. An autorun is a way for you to create a reactive computation (a function which runs whenever its reactive variables change) - see the section on reactivity from the docs. A find/fetch or a subscribe could happen inside of an autorun depending on your use case. This probably will become more clear once you learn more about how meteor works.
Essentially, when you subscribe to a dataset, it fills minimongo with that data, which is stored in the window's local storage. This is what populates the client's instance of that Mongo with data, otherwise, basically all queries will return undefined data or empty lists.
To summarize: Subscribe and Publish are used to give different data to different users. The most common example would be giving different data based on roles. Say, for instance, you have a web application where you can see a "public" and a "friend" profile.
Meteor.publish('user_profile', function (userId) {
if (Roles.userIsInRole(this.userId, 'can-view', userId)) {
return Meteor.users.find(userId, {
fields: {
public: 1,
profile: 1,
friends: 1,
interests: 1
}
});
} else {
return Meteor.users.find(userId, {
fields: { public: 1 }
});
}
});
Now if you logged in as a user who was not friends with this user, and did Meteor.subscribe('user_profile', 'theidofuser'), and did Meteor.users.findOne(), you would only see their public profile. If you added yourself to the can-view role of the user group, you would be able to see public, profile, friends, and interests. It's essentially for security.
Knowing that, here's how the answers to your questions breaks down:
Order of operations matters, in the sense that you will get undefined unless it's in a reactive block (like Tracker.autorun or Template.helpers).
you still need to use the subscribe when using fetch. All fetch really does is return an array instead of a cursor. To publish with foreign keys is a pretty advanced problem at times, I recommend using reywood:publish-composite, which handles the annoying details for you
Tracker.autorun watches reactive variables within the block and will rerun the function when one of them changes. You don't really ever use it instead of subscribing, you just use it to watch the variables in your scope.

How to commit and rollback transaction in parse cloud

I'm trying to insert an object in multiple table class, if error happens while inserting in any one of the class how to rollback to previous state like Begin, Commit and Rollback transation in MySQL server
Parse does not have roll-back feature based on their post:https://www.parse.com/questions/saveall-and-rollback--2
I don't think you can do transactions like in MySQL Server or as if you where having a unit of work in Entity Framework.
Best option I can think about is to use the promise pattern. With promises, your code can be much cleaner than the nested code you get with callbacks. This way you can deal with the erro handeling cases nicely but still not the same as transactions.

HTML 5 Web SQL Database Transaction commit or rollback when refreshing page

As written in the Safari Client-Side Storage and Offline Applications Programming Guide, rolling back a HTML 5 Web SQL Database transaction is done by returning true in the callback function provided as an error callback to a transaction the executeSql method:
The per-query error-handling callback
is rather straightforward. If the
callback returns true, the entire
transaction is rolled back. If the
callback returns false, the
transaction continues as if nothing
had gone wrong. Thus, if you are
executing a query that is optional—if
a failure of that particular query
should not cause the transaction to
fail—you should pass in a callback
that returns false. If a failure of
the query should cause the entire
transaction to fail, you should pass
in a callback that returns true.
For example if I have the following transaction (suppose the 'users' table has a UNIQUE constraint on the 'username' field and username 'test' already exists - which I'm trying to insert again, which should result in a constraint error):
database.transaction(function(transaction) {
transaction.executeSql(
"INSERT INTO users (username) VALUES('test')",
null,
dataCallback,
errorCallback
);
});
function errorCallback() {
return true; //this causes the rollback
}
I have two questions:
If I have to include many operations inside a transaction (for example I have to send some data using ajax to a server and wait for the response, etc.) and the user reloads the page before the response had arrived (which means that the errorCallback won't be called), will the transaction be commited or will it fail ?
Does anyone know how to rollback a Web SQL transaction manually ? For example if I want to rollback a transaction based on the result of an ajax call, how can it be done ? Should I run a query which contains an error to make sure that the error callback is called ?
Thanks.
The transaction will be committed.
Yes, to rollback explicitly, you must invoke invalid query explicitly. This is recommended workaround since the quick-and-dirty API is missing abort method.
Regarding AJAX, be ready all data, before you start a write transaction. You won't have any problem as you described. Use database constraint (UNIQUE, FOREIGNKEY) as much possible.
Have you found a way to do AJAX calls during the transaction? I haven't finished reading the whole spec, but so far it looks like once your SQLTransactionCallback or SQLTransactionSyncCallback returns, you can’t add any more stuff to the transaction — or can you? Maybe from the results callback?
Edit:
Now that I look again, the spec (which contains many fewer errors than the Apple document you linked to, but is not as easy to read) says this:
If the method [executeSql] was not invoked during the execution of a SQLTransactionCallback, SQLStatementCallback, or SQLStatementErrorCallback then raise an INVALID_STATE_ERR exception.
So I think that means there's no way to do it.
Further edit: No, wait! As long as the SQLStatementCallback takes some time to get called, you could busy-wait doing select 3 + 4 over and over again, each time from the statement callback of the previous select 3 + 4, until your AJAX call sets a flag somewhere that has the data you want. This is terrible programming (it'll eat lots of CPU for no good reason, might block lower-priority tasks like redisplaying the page) but I think it's probably the only way to keep a transaction open for an arbitrary period of time. Too bad you can't select 3 + 4, sleep(1) in SQLite.
In general SQLite (the underlying storage engine here) rolls back uncompleted transactions. I haven’t yet tested the page-reload error case you're asking about. I would be very surprised if it was committed.
By the way, thank you very much for posting this question. I had been trying to figure out how to get the transaction to rollback, even though it is meticulously documented in the original spec.

Categories