How to Handle two http requests from a distributed system?












0














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




  1. User can only signup/ sign in via Facebook

  2. On every successful signup Facebook sends back the some information like the users name, email and uid

  3. 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?










share|improve this question
























  • 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 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


















0














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




  1. User can only signup/ sign in via Facebook

  2. On every successful signup Facebook sends back the some information like the users name, email and uid

  3. 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?










share|improve this question
























  • 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 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
















0












0








0







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




  1. User can only signup/ sign in via Facebook

  2. On every successful signup Facebook sends back the some information like the users name, email and uid

  3. 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?










share|improve this question















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




  1. User can only signup/ sign in via Facebook

  2. On every successful signup Facebook sends back the some information like the users name, email and uid

  3. 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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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




















  • 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 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


















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














1 Answer
1






active

oldest

votes


















3














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.






share|improve this answer



















  • 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













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
});


}
});














draft saved

draft discarded


















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









3














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.






share|improve this answer



















  • 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


















3














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.






share|improve this answer



















  • 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
















3












3








3






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.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








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
















  • 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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Full-time equivalent

Bicuculline

さくらももこ