How to Handle two http requests from a distributed system?
We have an application where users can sign in only with Facebook. On successful Facebook login an another http rest call is made to store the name, email and some other information from Facebook login provider. We would end up with data consistency issues if The second RESTful service fail to store the information from fb to the the Mongodb
- User can only signup/ sign in via Facebook
- On every successful signup Facebook sends back the some information like the users name, email and uid
- We then store this information on our database immediately
So if the 3rd step fails, we loose the information about the user who signed up via Facebook.
loginWithFacebook() {
const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');
provider.addScope('user_friends');
provider.addScope('user_gender');
return new Promise<any>((resolve, reject) => {
this.afAuth.auth
.signInWithPopup(provider) // a call made to sign up via fb
.then(res => {
if (res) {
resolve(res);
if (res.additionalUserInfo.isNewUser) { // creatin profile only if he is a new user
this.createProfile(res); // a call to store the response in the db
}
this.setTokenSession(res.credential.accessToken);
}
}, err => {
console.log(err);
reject(err);
})
})
}
Is there a neat architectural way of orchestrating this?
node.js rest firebase http firebase-authentication
|
show 4 more comments
We have an application where users can sign in only with Facebook. On successful Facebook login an another http rest call is made to store the name, email and some other information from Facebook login provider. We would end up with data consistency issues if The second RESTful service fail to store the information from fb to the the Mongodb
- User can only signup/ sign in via Facebook
- On every successful signup Facebook sends back the some information like the users name, email and uid
- We then store this information on our database immediately
So if the 3rd step fails, we loose the information about the user who signed up via Facebook.
loginWithFacebook() {
const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');
provider.addScope('user_friends');
provider.addScope('user_gender');
return new Promise<any>((resolve, reject) => {
this.afAuth.auth
.signInWithPopup(provider) // a call made to sign up via fb
.then(res => {
if (res) {
resolve(res);
if (res.additionalUserInfo.isNewUser) { // creatin profile only if he is a new user
this.createProfile(res); // a call to store the response in the db
}
this.setTokenSession(res.credential.accessToken);
}
}, err => {
console.log(err);
reject(err);
})
})
}
Is there a neat architectural way of orchestrating this?
node.js rest firebase http firebase-authentication
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
I have updated my questions.
– Karty
Nov 11 at 19:35
1
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
1
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
1
@Karty You should be returning a promise fromcreateProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request aftercreateProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).
– Brad
Nov 11 at 20:04
|
show 4 more comments
We have an application where users can sign in only with Facebook. On successful Facebook login an another http rest call is made to store the name, email and some other information from Facebook login provider. We would end up with data consistency issues if The second RESTful service fail to store the information from fb to the the Mongodb
- User can only signup/ sign in via Facebook
- On every successful signup Facebook sends back the some information like the users name, email and uid
- We then store this information on our database immediately
So if the 3rd step fails, we loose the information about the user who signed up via Facebook.
loginWithFacebook() {
const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');
provider.addScope('user_friends');
provider.addScope('user_gender');
return new Promise<any>((resolve, reject) => {
this.afAuth.auth
.signInWithPopup(provider) // a call made to sign up via fb
.then(res => {
if (res) {
resolve(res);
if (res.additionalUserInfo.isNewUser) { // creatin profile only if he is a new user
this.createProfile(res); // a call to store the response in the db
}
this.setTokenSession(res.credential.accessToken);
}
}, err => {
console.log(err);
reject(err);
})
})
}
Is there a neat architectural way of orchestrating this?
node.js rest firebase http firebase-authentication
We have an application where users can sign in only with Facebook. On successful Facebook login an another http rest call is made to store the name, email and some other information from Facebook login provider. We would end up with data consistency issues if The second RESTful service fail to store the information from fb to the the Mongodb
- User can only signup/ sign in via Facebook
- On every successful signup Facebook sends back the some information like the users name, email and uid
- We then store this information on our database immediately
So if the 3rd step fails, we loose the information about the user who signed up via Facebook.
loginWithFacebook() {
const provider = new firebase.auth.FacebookAuthProvider();
provider.addScope('user_birthday');
provider.addScope('user_friends');
provider.addScope('user_gender');
return new Promise<any>((resolve, reject) => {
this.afAuth.auth
.signInWithPopup(provider) // a call made to sign up via fb
.then(res => {
if (res) {
resolve(res);
if (res.additionalUserInfo.isNewUser) { // creatin profile only if he is a new user
this.createProfile(res); // a call to store the response in the db
}
this.setTokenSession(res.credential.accessToken);
}
}, err => {
console.log(err);
reject(err);
})
})
}
Is there a neat architectural way of orchestrating this?
node.js rest firebase http firebase-authentication
node.js rest firebase http firebase-authentication
edited Nov 11 at 20:14
asked Nov 11 at 19:15
Karty
289520
289520
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
I have updated my questions.
– Karty
Nov 11 at 19:35
1
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
1
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
1
@Karty You should be returning a promise fromcreateProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request aftercreateProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).
– Brad
Nov 11 at 20:04
|
show 4 more comments
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
I have updated my questions.
– Karty
Nov 11 at 19:35
1
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
1
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
1
@Karty You should be returning a promise fromcreateProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request aftercreateProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).
– Brad
Nov 11 at 20:04
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
I have updated my questions.
– Karty
Nov 11 at 19:35
I have updated my questions.
– Karty
Nov 11 at 19:35
1
1
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
1
1
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
1
1
@Karty You should be returning a promise from
createProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request after createProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).– Brad
Nov 11 at 20:04
@Karty You should be returning a promise from
createProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request after createProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).– Brad
Nov 11 at 20:04
|
show 4 more comments
1 Answer
1
active
oldest
votes
Buckle up, because this is not a trivial problem.
If this is a true microservice architecture, where each service has it's own dedicated database, then you obviously can't efficiently perform a transaction. You might be able to do a 2-phase commit but that has problems of it's own, especially with long-lived DB locks.
A scalable approach to your problem is the Distributed Saga Pattern:
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
I think the above covers it pretty succinctly so I'm going to intentionally veer off on a tangent:
Distributed systems are hard to manage. Make sure you aren't violating YAGNI with your system architecture. If possible, ask yourself whether you really need a distributed architecture at this point.
Ensuring data consistency in a distributed system is a relatively complex
task that in most cases requires a dedicated coordinator service, extra code to manage it all and all the complexity that comes with all this extra machinery.
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53252262%2fhow-to-handle-two-http-requests-from-a-distributed-system%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Buckle up, because this is not a trivial problem.
If this is a true microservice architecture, where each service has it's own dedicated database, then you obviously can't efficiently perform a transaction. You might be able to do a 2-phase commit but that has problems of it's own, especially with long-lived DB locks.
A scalable approach to your problem is the Distributed Saga Pattern:
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
I think the above covers it pretty succinctly so I'm going to intentionally veer off on a tangent:
Distributed systems are hard to manage. Make sure you aren't violating YAGNI with your system architecture. If possible, ask yourself whether you really need a distributed architecture at this point.
Ensuring data consistency in a distributed system is a relatively complex
task that in most cases requires a dedicated coordinator service, extra code to manage it all and all the complexity that comes with all this extra machinery.
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
add a comment |
Buckle up, because this is not a trivial problem.
If this is a true microservice architecture, where each service has it's own dedicated database, then you obviously can't efficiently perform a transaction. You might be able to do a 2-phase commit but that has problems of it's own, especially with long-lived DB locks.
A scalable approach to your problem is the Distributed Saga Pattern:
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
I think the above covers it pretty succinctly so I'm going to intentionally veer off on a tangent:
Distributed systems are hard to manage. Make sure you aren't violating YAGNI with your system architecture. If possible, ask yourself whether you really need a distributed architecture at this point.
Ensuring data consistency in a distributed system is a relatively complex
task that in most cases requires a dedicated coordinator service, extra code to manage it all and all the complexity that comes with all this extra machinery.
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
add a comment |
Buckle up, because this is not a trivial problem.
If this is a true microservice architecture, where each service has it's own dedicated database, then you obviously can't efficiently perform a transaction. You might be able to do a 2-phase commit but that has problems of it's own, especially with long-lived DB locks.
A scalable approach to your problem is the Distributed Saga Pattern:
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
I think the above covers it pretty succinctly so I'm going to intentionally veer off on a tangent:
Distributed systems are hard to manage. Make sure you aren't violating YAGNI with your system architecture. If possible, ask yourself whether you really need a distributed architecture at this point.
Ensuring data consistency in a distributed system is a relatively complex
task that in most cases requires a dedicated coordinator service, extra code to manage it all and all the complexity that comes with all this extra machinery.
Buckle up, because this is not a trivial problem.
If this is a true microservice architecture, where each service has it's own dedicated database, then you obviously can't efficiently perform a transaction. You might be able to do a 2-phase commit but that has problems of it's own, especially with long-lived DB locks.
A scalable approach to your problem is the Distributed Saga Pattern:
Implement each business transaction that spans multiple services as a saga. A saga is a sequence of local transactions. Each local transaction updates the database and publishes a message or event to trigger the next local transaction in the saga. If a local transaction fails because it violates a business rule then the saga executes a series of compensating transactions that undo the changes that were made by the preceding local transactions.
I think the above covers it pretty succinctly so I'm going to intentionally veer off on a tangent:
Distributed systems are hard to manage. Make sure you aren't violating YAGNI with your system architecture. If possible, ask yourself whether you really need a distributed architecture at this point.
Ensuring data consistency in a distributed system is a relatively complex
task that in most cases requires a dedicated coordinator service, extra code to manage it all and all the complexity that comes with all this extra machinery.
edited Nov 11 at 19:38
answered Nov 11 at 19:25
Nik Kyriakides
8,573839105
8,573839105
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
add a comment |
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
1
1
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
My answer looks rather unnecessary after the OP edit.
– Nik Kyriakides
Nov 11 at 19:45
1
1
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
I think he doesn't really know what he's asking. :-/
– Brad
Nov 11 at 19:46
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
Oh well; I'll still leave it on. Perhaps it discourages a lost soul from unnecessarily doing a distributed architecture.
– Nik Kyriakides
Nov 11 at 19:50
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53252262%2fhow-to-handle-two-http-requests-from-a-distributed-system%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Please provide more details about what is in these requests, and how the data relates between the two. Ideally, you simply remove the need to do this. But, if you must, there are some ways around the problem, each with varying tradeoffs. Also, are both requests happening at the same time, or are they sequential?
– Brad
Nov 11 at 19:25
I have updated my questions.
– Karty
Nov 11 at 19:35
1
I think your edit makes my answer rather unnecessary. This is not a distributed system. If the REST call to store the data fails (because of a transient issue), just tell that to the user and ask them to sign up again.
– Nik Kyriakides
Nov 11 at 19:36
1
@Karty You need to add actual details about what you're sending/receiving for all of these API calls. The three steps you just listed out all require only one API call. I don't see what the problem is here. Also, I suspect your Facebook authentication is bungled a bit... while the API is a real hassle to deal with, it is possible to check your app's authentication status.
– Brad
Nov 11 at 19:46
1
@Karty You should be returning a promise from
createProfile()
, and then returning that promise here so that the outer promise all rolls up together. Additionally though, I don't see a massive risk here. Where is it that you're immediately calling another API request aftercreateProfile()
? Why not return the created profile with that request so whatever needs it can use it right away? Also, your server-side script shouldn't be returning until it is reasonably certain important data is committed and replicated in the DB (not always possible).– Brad
Nov 11 at 20:04