What you need is a message queuing system. There is one built-in to the Google Cloud platform called Pub/Sub. This method is not a trivial setup, nor is it too difficult. In fact 90% of the setup can be done in the API console interface. The last bit can be handled with a pub/sub library found on my github.
https://github.com/Spencer-Easton/Apps-Script-PubSubApp-Library
The basic outline follows:
1) User submission->Form Collection adds response to pub/sub responseQueue->Form Collection responds to form submit
2) Pub/Sub responseQueue->Form Processor preforms business logic->Form Processor adds response to processedQueue or Audit Log.
Note: Steps 1 and 2 run asynchronously from each other.
Form Collection Script
1) Add pubsub library: Mk1rOXBN8cJD6nl0qc9x5ukMLm9v2IJHf
2) Add GSApp library: MJ5317VIFJyKpi9HCkXOfS0MLm9v2IJHf
3) Open the scripts Developers Console Project.
--a) Add the pub/sub api.
--b) Add a service account under credentials. Download key as json.
--c) Open Big Data -> Pub/Sub in nav. menu
--d) Create the create topics: responseQueue
--e) Leave this open as we will set permissions for this topic from the Form Process script later
4) Copy the contents of the jsonKey to the scripts properties save it as jsonKey
5) Add the snippet of code:
function getTokenService(){
var jsonKey = JSON.parse(PropertiesService.getScriptProperties().getProperty("jsonKey"));
var privateKey = jsonKey.private_key;
var serviceAccountEmail = jsonKey.client_email;
var sa = GSApp.init(privateKey, ['https://www.googleapis.com/auth/pubsub'], serviceAccountEmail);
sa.addUser(serviceAccountEmail)
.requestToken();
return sa.tokenService(serviceAccountEmail);
}
6) Below is an example doGet() function:
function doGet(e){
try{
PubSubApp.setTokenService(getTokenService());
//Don't forget to set this to your scripts projectID
var pub = PubSubApp.PublishingApp('api-project-YourAPIProjectID');
var message = pub.newMessage();
message.data = Utilities.base64Encode(e.parameter.response);
pub.getTopic('responseQueue').publish(message);
return ContentService
.createTextOutput(e.parameter.callback+'(console.log("processing"))')
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}catch(e){throw new Error(e)}
}
Form Processor Script
1) Add this example snippet of code:
function doPost(e) {
var postBody = JSON.parse(e.postData.getDataAsString());
var messageData = Utilities.newBlob(Utilities.base64Decode(postBody.message.data)).getDataAsString();
//Spreadsheet is used for an audit log. Add you own spreadshhetid here.
var ss = SpreadsheetApp.openById(SpreadSheetId).getSheetByName("Log");
ss.appendRow([new Date(), messageData, JSON.stringify(postBody,undefined,2)])
return 200;
}
2) Publish Script as a Web App
3) Deploy script to the Chrome Store. (You can leave it in draft mode)
4) Get the scripts deployed URL and save it for later. It will look like:
https://script.google.com/a/macros/{DOMAIN}/s/AKfycbyEeHW32Pa...5gLHa/exec
5) Open the scripts Developers Console Project.
--a) Add the pub/sub api.
--b) Add a service account under credentials. Download key as json.
6) Go back to the Form Collection Dev Console
--a) Add the URL from step 5 to APIs & Auth -> Push -> Add Domain
--b) In the From Collection Dev Console Pub/Sub setting add the service account email from step 5 to the responseQueue permissions as a subscriber.
--c) Click Add Subscriber
on the responseQueue topic. Give the subscription a memorable name like formProcessorOne. Select Push then enter the same URL you got in step 4.
--d) Click More Options
enter a Timeout limit under acknowledge deadline. This is the amount of time you would expect your Form Processing script to finish in. If the deadline passes with no acknowledgement the message goes back into the queue.
Finally
When messages get posted to your Form Collector the response parameter is added to the responseQueue. The responseQueue pushes the message to the From Processor script.
Note: Depending on the amount of traffic and the length of the business logic on you Form Processor you may get the too many concurrent scripts error. Never fear because you set a timeout the message goes back to the queue and will be attempted again.
So this may possibly be overkill for you project depending on your scaling needs. The other answers in this thread are also both reasonable. If you are expecting low volume using the property service as a working queue would work with proper locking.
Also using HtmlService to host your html gives you access to google.script.run which is similar to jquerys $.get(), but maintains access and authentication with your script transparently.