加快Google Apps脚本的速度,这样我就可以在Shopify 5秒内返回成功响应 [英] Quicken google apps script so I can return success response within Shopify 5 second limit

查看:43
本文介绍了加快Google Apps脚本的速度,这样我就可以在Shopify 5秒内返回成功响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我写的这个Google Apps脚本,我正在将其用作Web应用程序,作为Shopify Webhook的终结点.

I have this google apps script I wrote that I'm using as a web app as an endpoint for a Shopify webhook.

我遇到的问题是Shopify有5秒的限制才能收到成功响应,否则webhook将再次触发以确保您不会错过它.

The issue I'm having is that Shopify has a 5 second limit to receive a success response otherwise the webhook will fire again to ensure you don't miss it.

问题是我的脚本花了太长时间才能完成触发重复的Webhook的操作,该Webhook多次运行我的代码,这是我不希望的.

The problem is my script takes too long to finish triggering a duplicate webhook which runs my code multiple times which I don't want.

是否可以更快地响应或清理脚本以更快地完成?

Is there a way to respond quicker or clean up my script to finish quicker?

请注意:由于我仍在开发此应用,因此确切值可能会更改或最终版本中不同,因此我需要轻松修改脚本.(另外,我需要一种方法,如果缺少值,它将使该列留空,因此不会将值与列标题混淆)

PLEASE NOTE: I need my script to be easily modified since exact values might change or be different in final version as I'm still developing this app. (additionally I need a way that if a value is missing it will leave that column blank, hence not mixing up value with column headers)

function doPost(e){
  var data = JSON.parse(e.postData.contents);
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
 
  var l = data.line_items.length; 
 
  for (var i=0;i<l;i++){
  var prop = data.line_items[i].properties;


  if (prop.length>0){
  var pdf = prop.find(function(x) {if(x.name == "_pdf") return x});
  if (!pdf){pdf = "Prop not found";}else{pdf = pdf.value};
  
  var shape = prop.find(function(x) {if(x.name.toLowerCase() == "shape") return x});
  if (!shape){shape = "Prop not found";}else{shape = shape.value};
  
  var test = prop.find(function(x) {if(x.name == "test") return x});
  if (!test){test = "Prop not found";}else{test = test.value};

  }else{
  var pdf = "N/A"
  var shape = "N/A"
  var test = "N/A"
  };


  var count = "Item "+ (i+1) + " of " + l;
  var qty = data.line_items[i].quantity;
  var title = data.line_items[i].title;
  var id = data.id.toString();
  var email = data.email;
  var totalPrice = data.total_price;
  var discounts = data.total_discounts;
  var acceptAds = data.buyer_accepts_marketing;
  var orderStatus = data.order_status_url;
  var addr = data.shipping_address.address1;
  var city = data.shipping_address.city;
  var state = data.shipping_address.province;
  var zip = data.shipping_address.zip;
  var phone = data.shipping_address.phone;
  var firstName = data.shipping_address.first_name;
  var lastName = data.shipping_address.last_name;
  var orderNum = data.name;
  var d = new Date(data.created_at).toLocaleString();
  ss.appendRow([d,orderNum,email,count,title,shape,test,qty,totalPrice,discounts,pdf,firstName,lastName,addr,city,state,zip,phone,orderStatus]);
  
if (pdf != "N/A"){
if (pdf != "Prop not found"){
  var res = UrlFetchApp.fetch(pdf);
  var blob = res.getBlob();
  var createFile = DriveApp.getFolderById('xxxxxxxxxxxxx').createFile(blob.getAs('application/pdf'));
  var fileName = orderNum + " " + qty;
  createFile.setName(fileName);
}}
  };
}

推荐答案

比使用 PropertiesService ,但我喜欢将表格用作队列.(我将它与要求在3秒钟内响应的服务一起使用.)不仅操作起来更容易,而且在使用由

It's slower than using the PropertiesService, but I like using Sheets as a queue. (I use this with services that require responses within 3 seconds.) Not only is it easier to work with, but I've actually had issues with using Properties that are addressed with the appendRow() method:

在电子表格上添加一行.此操作是原子操作;这样可以防止出现这样的问题:用户要求最后一行然后写入该行,并且在获取最后一行并将其写入之间发生了中间的变异.

Appends a row to the spreadsheet. This operation is atomic; it prevents issues where a user asks for the last row, and then writes to that row, and an intervening mutation occurs between getting the last row and writing to it.

当您收到POST数据时,只需将其添加到队列中并终止.Apps脚本将发送200成功响应,因此Shopify不应发送重复的请求.

When you receive the POST data, simply add it to the queue and terminate. Apps Script will send a 200 success response, so Shopify shouldn't send duplicate requests.

然后有一个时间驱动的触发器在您选择的时间间隔内运行 processQueue()函数.

Then have a time-driven trigger that runs a processQueue() function at the interval of your choice.

function doPost(e) {
  const queue = new Queue(SpreadsheetApp.getActive().getId(), "Unprocessed", "Processed");
  queue.append(e.postData.contents, skipRefresh = true);
}

function processQueue() {
  const queue = new Queue(SpreadsheetApp.getActive().getId(), "Unprocessed", "Processed");
  while (queue.hasNext()) {
    try {
      const data = JSON.parse(queue.next());
      
      doSomethingWithShopifyData(data); // Process your data
      
      queue.moveToProcessed();
    } catch (error) {
      console.error(error);
      queue.skip();
    }
  }
}

function doSomethingWithShopifyData(data) { /* your existing code, but with appropriate modifications */ }

这是我用来将电子表格抽象为队列的类.我将其设置为保留所有将其从未处理的表移动到已处理的表的数据.您可能希望仅在处理后删除数据.

Here's the class I use to abstract the spreadsheet into a queue. I have it setup to preserve all of the data moving it from an unprocessed to a processed sheet. You may prefer to simply delete the data once processed.

/**
 * A spreadsheet is used as a makeshift queue for processing requests asynchronously.
 * @param {string} spreadsheetId - The ID of the spreadsheet to be used for the queue.
 * @param {string} unprocessedSheetName - The name of the sheet to be used for storing unprocessed items.
 * @param {string} processedSheetName - The name of the sheet to be used for storing processed items.
 */
class Queue {
  constructor(spreadsheetId, unprocessedSheetName, processedSheetName) {
    this.index = 0;
    this.row = 1;
    this.spreadsheet = SpreadsheetApp.openById(spreadsheetId);
    this.unprocessedSheet = this.spreadsheet.getSheetByName(unprocessedSheetName);
    this.processedSheet = this.spreadsheet.getSheetByName(processedSheetName);
  }
  
  /**
   * Determines whether calling next() will return an item.
   * @returns {boolean}
   */
  hasNext() {
    if (this.unprocessedValues == null) { this.refreshUnprocessedValues(); }
    return this.index < this.unprocessedValues.length;
  }
  
  /**
   * Get and save the unprocessed element values to the queue.
   * @returns {object[]}
   */
  refreshUnprocessedValues() {
    try {
      const range =this.unprocessedSheet.getRange(1, 1, this.unprocessedSheet.getLastRow());
      this.unprocessedValues = range.getValues();
    } catch (error) {
      this.unprocessedValues = [];
    }
    return this.unprocessedValues;
  }
  
  /**
   * Get the next element from the queue.
   * @returns {string}
   */
  next() {
    return this.unprocessedValues[this.index++][0];
  }
  
  /**
   * Skip the current queue element. Update row property to maintain synchronization
   * with the spreadsheet range.
   */
  skip() {
    this.row++;
  }
  
  /**
   * Add new data to the queue for processing.
   * @param {string} data - The data to add to the queue.
   * @param {boolean} [skipRefresh] - Default: false. If true, will skip refreshing the queue values.
   */
  append(data, skipRefresh) {
    this.unprocessedSheet.appendRow([data]);
    if (!skipRefresh) { this.refreshUnprocessedValues(); }
  }
  
  /**
   * Move a payload out of the unprocessed sheet and into the processed sheet. Uses the payload
   * at the top of the unprocessed range.
   */
  moveToProcessed() {
    const cell = this.unprocessedSheet.getRange(this.row, 1);
    
    // Move into processed sheet
    this.processedSheet.appendRow([cell.getValue()]);
    
    // Move out of unprocessed sheet
    cell.deleteCells(SpreadsheetApp.Dimension.ROWS);
  }
}

这篇关于加快Google Apps脚本的速度,这样我就可以在Shopify 5秒内返回成功响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆