问:
Google Scripts - Error When Calling Function in Another Function
I'm posting the entirety of the code I have below.

I'm working in Google Scripts, pulling some data from a sheet that is constantly changing, performing calculations and then repopulating the sheet.

The data is being called into an app, so I'm trying to do the calculations as quickly as possible (so if anyone can tell me more efficient ways to do this that would be helpful too).

When I try to call the invoicePrice() function or the tiers() function I get a TypeError: function cannot be found.

```<code>function invoicePrice() {
      // define row to do calculations on
      var AVals = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange("A1:A1000").getValues();
      var ALast = AVals.filter(String).length;

      // Set order No. here

      var orderNoPrev = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast - 1, 3).getValue();
      var orderNo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 3).setValue(orderNoPrev + 1);
      var total = 0;

      // invoicePrice the total number of items
      var itemRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 4, 1, 14).getValues()[0];

      // set the values of the constants on the Products page

      var priceRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("F1:F1000").getValues();
      var pLast = priceRange.filter(String).length;
      var pGrab = priceRange.splice(0,pLast);

      var invoicePrice = 0;

      // set weight of case values

      var weightRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("V1:V1000").getValues();
      var wLast = weightRange.filter(String).length;
      var wGrab = weightRange.splice(0,wLast);

      for (var i = 0, len = 13; i <= len; i++) {
          // SUBTOTAL THE ORDER AMOUNT
          var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();

          total += orderAmount;

          // SET/KG PRICES
          var perKGInvoice = pGrab[i + 1].map(Number);

          // SET WEIGHTS
          var weights = wGrab[i + 1].map(Number);

          // SET CASE PRICE
          var casePrice = perKGInvoice * weights;

          // SUM OF PRODUCT PRICE * ORDER AMOUNT * WEIGHT OF CASE
          invoicePrice += orderAmount * perKGInvoice * weights;

      }
    Logger.log(invoicePrice, ALast, pGrab, wGrab);
    return [invoicePrice, ALast, pGrab, wGrab];

  }

  function tiers() {
      var invoicePriceCall = invoicePrice();
      var invoicePrice = invoicePriceCall[0];
      var ALast = invoicePriceCall[1];

      var beefDiscount = 0;
      var sfDiscount = 0;
      var currentTier = ""

      // Set the invoice order value required ($ amount)

      var tier1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 3).getValue();
      var tier2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 3).getValue();
      var tier3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 3).getValue();
      var tier4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 3).getValue();
      var tier5 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 3).getValue();
      var minNotmet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(10, 3).getValue();

      // Set the discount tier levels for beef (% discount)
      var tier1BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 4).getValue();
      var tier2BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 4).getValue();
      var tier3BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 4).getValue();
      var tier4BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 4).getValue();
      var tier5BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 4).getValue();

      var tier1SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 5).getValue();
      var tier2SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 5).getValue();
      var tier3SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 5).getValue();
      var tier4SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 5).getValue();
      var tier5SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 5).getValue();

      if (invoicePrice < tier1) {
          beefDiscount = tier1BeefDiscount;
          sfDiscount = tier1SfDiscount;
          currentTier = "Minimum Not Met"
      }
      else if (invoicePrice < tier2) {
          beefDiscount = tier1BeefDiscount;
          sfDiscount = tier1SfDiscount;
          currentTier = "Tier 1"
      }
      else if (invoicePrice < tier3) {
          beefDiscount = tier2BeefDiscount;
          sfDiscount = tier2SfDiscount;
          currentTier = "Tier 2"
      }
      else if (invoicePrice < tier4) {
          beefDiscount = tier3BeefDiscount;
          sfDiscount = tier3SfDiscount;
          currentTier = "Tier 3";
      }
      else if (invoicePrice < tier5) {
          beefDiscount = tier4BeefDiscount;
          sfDiscount = tier4SfDiscount;
          currentTier = "Tier 4";
      }
      else {
          beefDiscount = tier5BeefDiscount;
          sfDiscount = tier5SfDiscount;
          currentTier = "Tier 5";
      }

      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 20).setValue(beefDiscount);
      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 21).setValue(sfDiscount);
      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 22).setValue(currentTier);

      return [beefDiscount, sfDiscount, tier1];

  }

  function calcsOnColumns2() {

      // call price range and weight from previous function
      var invoicePriceCall = invoicePrice();
      var invoicePrice = invoicePriceCall[0];
      var ALast = invoicePriceCall[1];
      var priceRange = invoicePriceCall[2];
      var weightRange = invoicePriceCall[3];

      // call tiers function
      var tiers = tiers();
      var beefDiscount = tiers[0];
      var sfDiscount = tiers[1];
      var tier1 = tiers[2];

      // set sums to 0

      var beefSum = 0;
      var sfSum = 0

      for (var i = 0, len = 13; i <= len; i++) {
          // SUBTOTAL THE ORDER AMOUNT
          var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();

          // SET/KG PRICES
          var perKGInvoice = priceRange[i + 1].map(Number);

          // SET WEIGHTS
          var weights = weightRange[i + 1].map(Number);

          // SET CASE PRICE
          var casePrice = perKGInvoice * weights;

          // Split up seafood and beef with if statement:

          if (i < 9) {
              // set discount case price
              var discountCaseBeef = perKGInvoice - (perKGInvoice * beefDiscount);
              // set the total price of the discounted cases in the order (ie, order price * discount)
              var beefCaseOrder = discountCaseBeef * orderAmount * weights;
              beefSum += beefCaseOrder;
              // Nice and Formatted sheet
              var casePrice = perKGInvoice * weights;

              if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseBeef.toFixed(2) + "/kg = ~$" + beefCaseOrder.toFixed(2)); }

          }

          else {
              var discountCaseSF = perKGInvoice - (perKGInvoice * sfDiscount);
              // set the total price of the discounted cases in the order (ie, order price * discount)
              var sfCaseOrder = discountCaseSF * orderAmount * weights;
              sfSum += sfCaseOrder;
              // Nice and Formatted sheet
              var casePrice = perKGInvoice * weights;
              if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseSF.toFixed(2) + "/kg = ~$" + sfCaseOrder.toFixed(2)); }

          }

          if (i == len) {
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 24).setValue(beefSum);
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 25).setValue(sfSum);
              // if statement to go here if min order size not met

              var sumOfSums = beefSum + sfSum;
              // swap out 75 with referenced value
              if (sumOfSums > tier1) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue(sumOfSums) }
              // swap out phrase with changable phrase
              else { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue("Minimum order size not met") }

              var totalDiscount = invoicePrice - sumOfSums

              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 29).setValue(totalDiscount);
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 30).setValue(invoicePrice);

          }

      }

  }
</code>```

答:
Problem

A correctly declared function (invoicePrice), when called from another function (calcsOnColumns2) is undefined.

Steps to reproduce

Imagine you have three functions named A,B,C, then calling B causes your error:

```<code>function A() {
  var A = 0;
  return [A];
}

function C() {
  var a = A();
  var A = a[0];
}

function B() {
  A();
  C();
}
</code>```

You probably noticed that this is what your functions boil down to - the behaviour is due to hoisting:

function B calls A, which returns an Array with first element 0;

[never happens] function C calls function A and overrides A to output of A;

Instead, on step two A is declared to be equal to first element of a and only then A is called. Since a gets its value from call to A, A will be undefined and, as a result: [undefined]() -> "is not a function"

Optimization

Stay DRY (don't repeat yourself) - when you see code that looks the same or has the same structure, consider making it reusable (making it a function, class, object, a variable - it depends). It makes your code readable and easier to debug, but a lot of the time it saves you extra calls to APIs, recalcs and thus time (especially if you repeat I/O).

Don't use comments unless strictly necessary (reduces readability a lot - crucial if you need others to help debug your code or doing it yourself [may sound counter-intuitive, but you'll be surprized]).

Don't put I/O (getRange(),getValue()) in loops unless having no choice - input / output is always slow, so it is usually better to load everything into memory and work on data there.

Keep consistent scope: if you declare a variable, every accessor should be either in the same scope or nested (e.g. don't declare two vars of the same name inside if...else, move it to outer scope).

Use TypeScript or at least JSDoc - will keep you from going insane while trying to understand why your function expected one type and received another (just as in your case) [UPD: I've also added JSDOC comments to solution].

I've applied a few optimizations to your script, take a look (please, check before using, since we don't have sample data, I couldn't test it). There is a lot more you can do (especially regarding the loop in calcsOnColumns2), but that should be a start:

/**
 * [Your decription here]
 * @returns {Number[]}
 */
function invoicePrice() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var subtotalDisplaySheet = ss.getSheetByName('SubtotalDisplay');

    // define row to do calculations on
    var AVals = subtotalDisplaySheet.getRange("A1:A1000").getValues();
    var ALast = AVals.filter(String).length;

    // Set order No. here
    var orderNoPrev = subtotalDisplaySheet.getRange(ALast - 1, 3).getValue();
    var orderNo = subtotalDisplaySheet.getRange(ALast, 3).setValue(orderNoPrev + 1);

    // invoicePrice the total number of items
    var itemRange = subtotalDisplaySheet.getRange(ALast, 4, 1, 14).getValues()[0];

    // set the values of the constants on the Products page
    var productsSheet = ss.getSheetByName("Products");

    var priceRange = productsSheet.getRange("F1:F1000").getValues();
    var pLast = priceRange.filter(String).length;
    var pGrab = priceRange.splice(0, pLast);

    var outputInvoicePrice = 0;

    var weightRange = productsSheet.getRange("V1:V1000").getValues();
    var wLast = weightRange.filter(String).length;
    var wGrab = weightRange.splice(0, wLast);

    var orderAmounts = subtotalDisplaySheet.getRange(Alast, 17).getValues();

    var total = 0;
    for (var i = 0, len = 13; i <= len; i++) {
        var nextI = i + 1;

        var orderAmount = orderAmounts[0][i + 4];

        total += orderAmount;

        var perKGInvoice = pGrab[nextI].map(Number);
        var weights = wGrab[nextI].map(Number);

        var casePrice = perKGInvoice * weights;

        outputInvoicePrice += orderAmount * casePrice;
    }

    Logger.log(outputInvoicePrice, ALast, pGrab, wGrab);
    return [outputInvoicePrice, ALast, pGrab, wGrab];
}

/**
 * Gets values from 5 rows in
 * a column starting from row 3
 * @param {Sheet} sheet
 * @param {Number} column
 * @returns {*[]}
 */
function getGridValues(sheet, column) {
    var range = sheet.getRange(3, column, 5, 1);
    return range
        .getValues()
        .map(function (row) {
            return row[0];
        });
}

/**
 * [Your decription here]
 * @returns {Number[]}
 */
function tiers() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var discountGridSheet = ss.getSheetByName("DiscountGrid");

    var invoicePriceCall = invoicePrice();
    var outputInvoicePrice = invoicePriceCall[0];
    var ALast = invoicePriceCall[1];

    var beefDiscount = 0;
    var sfDiscount = 0;
    var currentTier = "";

    var tierValues = getGridValues(discountGridSheet, 3);
    var tier1 = tierValues[0];
    var tier2 = tierValues[1];
    var tier3 = tierValues[2];
    var tier4 = tierValues[3];
    var tier5 = tierValues[4];

    var minNotmet = discountGridSheet.getRange(10, 3).getValue();

    var tierBeefDiscountValues = getGridValues(discountGridSheet, 4);
    var tier1BeefDiscount = tierBeefDiscountValues[0];
    var tier2BeefDiscount = tierBeefDiscountValues[1];
    var tier3BeefDiscount = tierBeefDiscountValues[2];
    var tier4BeefDiscount = tierBeefDiscountValues[3];
    var tier5BeefDiscount = tierBeefDiscountValues[4];

    var tierSfDiscountValues = getGridValues(discountGridSheet, 5);
    var tier1SfDiscount = tierSfDiscountValues[0];
    var tier2SfDiscount = tierSfDiscountValues[1];
    var tier3SfDiscount = tierSfDiscountValues[2];
    var tier4SfDiscount = tierSfDiscountValues[3];
    var tier5SfDiscount = tierSfDiscountValues[4];

    if (outputInvoicePrice < tier1) {
        beefDiscount = tier1BeefDiscount;
        sfDiscount = tier1SfDiscount;
        currentTier = "Minimum Not Met";
    }
    else if (outputInvoicePrice < tier2) {
        beefDiscount = tier1BeefDiscount;
        sfDiscount = tier1SfDiscount;
        currentTier = "Tier 1";
    }
    else if (outputInvoicePrice < tier3) {
        beefDiscount = tier2BeefDiscount;
        sfDiscount = tier2SfDiscount;
        currentTier = "Tier 2";
    }
    else if (outputInvoicePrice < tier4) {
        beefDiscount = tier3BeefDiscount;
        sfDiscount = tier3SfDiscount;
        currentTier = "Tier 3";
    }
    else if (outputInvoicePrice < tier5) {
        beefDiscount = tier4BeefDiscount;
        sfDiscount = tier4SfDiscount;
        currentTier = "Tier 4";
    }
    else {
        beefDiscount = tier5BeefDiscount;
        sfDiscount = tier5SfDiscount;
        currentTier = "Tier 5";
    }

    var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay");
    var subtotalDisplayRange = subtotalDisplaySheet.getRange(ALast, 20, 3, 1);
    subtotalDisplayRange.setValues([
        [beefDiscount],
        [sfDiscount],
        [currentTier]
    ]);

    return [beefDiscount, sfDiscount, tier1];
}

/**
 * Foramts amount string
 * @param {Number} amount
 * @returns {Function}
 */
function formatAmount(amount) {
    return function (discount, caseOrder) {
        return amount + " cases @" + discount.toFixed(2) + "/kg = ~$" + caseOrder.toFixed(2);
    };
}

/**
 * Counts sum by discount, amount and weights
 * @param {Number} amount
 * @param {Number} weights
 * @returns {Number}
 */
function countSum(amount, weights) {
    return function (discount) {
        return discount * amount * weights;
    };
}

/**
 * Counts discount case per Kg
 * @param {Number} perKG
 * @returns {Number}
 */
function countDiscountCase(perKG) {
    return function (discount) {
        return perKG - (perKG * discount);
    };
}

/**
 * [Your decription here]
 */
function calcsOnColumns2() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay");

    var invoicePriceCall = invoicePrice();
    var outputInvoicePrice = invoicePriceCall[0];
    var ALast = invoicePriceCall[1];
    var priceRange = invoicePriceCall[2];
    var weightRange = invoicePriceCall[3];

    var tiers = tiers();
    var beefDiscount = tiers[0];
    var sfDiscount = tiers[1];
    var tier1 = tiers[2];

    var beefSum = 0;
    var sfSum = 0;

    var orderAmounts = subtotalDisplaySheet.getRange(ALast, 17).getValues();

    for (var i = 0, len = 13; i <= len; i++) {
        var orderAmount = orderAmounts[0][i + 4];

        var nextI = i + 1;

        var perKGInvoice = priceRange[nextI].map(Number);
        var weights = weightRange[nextI].map(Number);

        var casePrice = perKGInvoice * weights;

        var subtotalRange = subtotalDisplaySheet.getRange(ALast, i + 32);

        var formatAmountOrder = formatAmount(orderAmount);
        var countDisountSum = countSum(orderAmount, weights);
        var countPerKGCase = countDiscountCase(perKGInvoice);

        // Split up seafood and beef with if statement:
        if (i < 9) {
            var discountCaseBeef = countPerKGCase(beefDiscount);
            var beefCaseOrder = countDisountSum(discountCaseBeef);
            beefSum += beefCaseOrder;
        } else {
            var discountCaseSF = countPerKGCase(sfDiscount);
            var sfCaseOrder = countDisountSum(discountCaseSF);
            sfSum += sfCaseOrder;
        }

        if (orderAmount) {
            subtotalRange.setValue(
                i < 9 ?
                    formatAmountOrder(discountCaseBeef, beefCaseOrder) :
                    formatAmountOrder(discountCaseSF, sfCaseOrder)
            );
        }

        if (i == len) {
            subtotalDisplaySheet.getRange(ALast, 24).setValue(beefSum);
            subtotalDisplaySheet.getRange(ALast, 25).setValue(sfSum);
            // if statement to go here if min order size not met

            var subtotalRange = subtotalDisplaySheet.getRange(ALast, 27);

            var sumOfSums = beefSum + sfSum;

            subtotalRange.setValue(sumOfSums > tier1 ? "Minimum order size not met" : sumOfSums);

            var totalDiscount = outputInvoicePrice - sumOfSums;

            subtotalDisplaySheet.getRange(ALast, 29).setValue(totalDiscount);
            subtotalDisplaySheet.getRange(ALast, 30).setValue(outputInvoicePrice);
        }
    }

}```

Notes

Although modern JavaScript will help you avoid the issue, you should
never override any variable names unless you know exactly why you
are doing that (i++ is an example, however functional style will
say that even this is problematic).

Never truncate error messages / code when posting on SO for the sake of readability -knowing what exactly happened is invaluable for us to help you (invoicePrice is undefined says so much more).

References

Hoisting in JavaScript

Body:
I'm posting the entirety of the code I have below.

I'm working in Google Scripts, pulling some data from a sheet that is constantly changing, performing calculations and then repopulating the sheet.

The data is being called into an app, so I'm trying to do the calculations as quickly as possible (so if anyone can tell me more efficient ways to do this that would be helpful too).

When I try to call the invoicePrice() function or the tiers() function I get a TypeError: function cannot be found.

function invoicePrice() {
      // define row to do calculations on
      var AVals = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange("A1:A1000").getValues();
      var ALast = AVals.filter(String).length;

      // Set order No. here

      var orderNoPrev = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast - 1, 3).getValue();
      var orderNo = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 3).setValue(orderNoPrev + 1);
      var total = 0;

      // invoicePrice the total number of items
      var itemRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 4, 1, 14).getValues()[0];

      // set the values of the constants on the Products page

      var priceRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("F1:F1000").getValues();
      var pLast = priceRange.filter(String).length;
      var pGrab = priceRange.splice(0,pLast);

      var invoicePrice = 0;

      // set weight of case values

      var weightRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Products").getRange("V1:V1000").getValues();
      var wLast = weightRange.filter(String).length;
      var wGrab = weightRange.splice(0,wLast);

      for (var i = 0, len = 13; i <= len; i++) {
          // SUBTOTAL THE ORDER AMOUNT
          var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();

          total += orderAmount;

          // SET/KG PRICES
          var perKGInvoice = pGrab[i + 1].map(Number);

          // SET WEIGHTS
          var weights = wGrab[i + 1].map(Number);

          // SET CASE PRICE
          var casePrice = perKGInvoice * weights;

          // SUM OF PRODUCT PRICE * ORDER AMOUNT * WEIGHT OF CASE
          invoicePrice += orderAmount * perKGInvoice * weights;

      }
    Logger.log(invoicePrice, ALast, pGrab, wGrab);
    return [invoicePrice, ALast, pGrab, wGrab];

  }

  function tiers() {
      var invoicePriceCall = invoicePrice();
      var invoicePrice = invoicePriceCall[0];
      var ALast = invoicePriceCall[1];

      var beefDiscount = 0;
      var sfDiscount = 0;
      var currentTier = ""

      // Set the invoice order value required ($ amount)

      var tier1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 3).getValue();
      var tier2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 3).getValue();
      var tier3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 3).getValue();
      var tier4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 3).getValue();
      var tier5 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 3).getValue();
      var minNotmet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(10, 3).getValue();

      // Set the discount tier levels for beef (% discount)
      var tier1BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 4).getValue();
      var tier2BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 4).getValue();
      var tier3BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 4).getValue();
      var tier4BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 4).getValue();
      var tier5BeefDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 4).getValue();

      var tier1SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(3, 5).getValue();
      var tier2SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(4, 5).getValue();
      var tier3SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(5, 5).getValue();
      var tier4SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(6, 5).getValue();
      var tier5SfDiscount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DiscountGrid").getRange(7, 5).getValue();

      if (invoicePrice < tier1) {
          beefDiscount = tier1BeefDiscount;
          sfDiscount = tier1SfDiscount;
          currentTier = "Minimum Not Met"
      }
      else if (invoicePrice < tier2) {
          beefDiscount = tier1BeefDiscount;
          sfDiscount = tier1SfDiscount;
          currentTier = "Tier 1"
      }
      else if (invoicePrice < tier3) {
          beefDiscount = tier2BeefDiscount;
          sfDiscount = tier2SfDiscount;
          currentTier = "Tier 2"
      }
      else if (invoicePrice < tier4) {
          beefDiscount = tier3BeefDiscount;
          sfDiscount = tier3SfDiscount;
          currentTier = "Tier 3";
      }
      else if (invoicePrice < tier5) {
          beefDiscount = tier4BeefDiscount;
          sfDiscount = tier4SfDiscount;
          currentTier = "Tier 4";
      }
      else {
          beefDiscount = tier5BeefDiscount;
          sfDiscount = tier5SfDiscount;
          currentTier = "Tier 5";
      }

      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 20).setValue(beefDiscount);
      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 21).setValue(sfDiscount);
      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 22).setValue(currentTier);

      return [beefDiscount, sfDiscount, tier1];

  }

  function calcsOnColumns2() {

      // call price range and weight from previous function
      var invoicePriceCall = invoicePrice();
      var invoicePrice = invoicePriceCall[0];
      var ALast = invoicePriceCall[1];
      var priceRange = invoicePriceCall[2];
      var weightRange = invoicePriceCall[3];

      // call tiers function
      var tiers = tiers();
      var beefDiscount = tiers[0];
      var sfDiscount = tiers[1];
      var tier1 = tiers[2];

      // set sums to 0

      var beefSum = 0;
      var sfSum = 0

      for (var i = 0, len = 13; i <= len; i++) {
          // SUBTOTAL THE ORDER AMOUNT
          var orderAmount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 4).getValue();

          // SET/KG PRICES
          var perKGInvoice = priceRange[i + 1].map(Number);

          // SET WEIGHTS
          var weights = weightRange[i + 1].map(Number);

          // SET CASE PRICE
          var casePrice = perKGInvoice * weights;

          // Split up seafood and beef with if statement:

          if (i < 9) {
              // set discount case price
              var discountCaseBeef = perKGInvoice - (perKGInvoice * beefDiscount);
              // set the total price of the discounted cases in the order (ie, order price * discount)
              var beefCaseOrder = discountCaseBeef * orderAmount * weights;
              beefSum += beefCaseOrder;
              // Nice and Formatted sheet
              var casePrice = perKGInvoice * weights;

              if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseBeef.toFixed(2) + "/kg = ~$" + beefCaseOrder.toFixed(2)); }

          }

          else {
              var discountCaseSF = perKGInvoice - (perKGInvoice * sfDiscount);
              // set the total price of the discounted cases in the order (ie, order price * discount)
              var sfCaseOrder = discountCaseSF * orderAmount * weights;
              sfSum += sfCaseOrder;
              // Nice and Formatted sheet
              var casePrice = perKGInvoice * weights;
              if (orderAmount) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, i + 32).setValue(orderAmount + " cases @" + discountCaseSF.toFixed(2) + "/kg = ~$" + sfCaseOrder.toFixed(2)); }

          }

          if (i == len) {
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 24).setValue(beefSum);
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 25).setValue(sfSum);
              // if statement to go here if min order size not met

              var sumOfSums = beefSum + sfSum;
              // swap out 75 with referenced value
              if (sumOfSums > tier1) { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue(sumOfSums) }
              // swap out phrase with changable phrase
              else { SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 27).setValue("Minimum order size not met") }

              var totalDiscount = invoicePrice - sumOfSums

              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 29).setValue(totalDiscount);
              SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SubtotalDisplay").getRange(ALast, 30).setValue(invoicePrice);

          }

      }

  }

Body:
Problem

A correctly declared function (invoicePrice), when called from another function (calcsOnColumns2) is undefined.

Steps to reproduce

Imagine you have three functions named A,B,C, then calling B causes your error:

function A() {
  var A = 0;
  return [A];
}

function C() {
  var a = A();
  var A = a[0];
}

function B() {
  A();
  C();
}

You probably noticed that this is what your functions boil down to - the behaviour is due to hoisting:

function B calls A, which returns an Array with first element 0;

[never happens] function C calls function A and overrides A to output of A;

Instead, on step two A is declared to be equal to first element of a and only then A is called. Since a gets its value from call to A, A will be undefined and, as a result: [undefined]() -> "is not a function"

Optimization

Stay DRY (don't repeat yourself) - when you see code that looks the same or has the same structure, consider making it reusable (making it a function, class, object, a variable - it depends). It makes your code readable and easier to debug, but a lot of the time it saves you extra calls to APIs, recalcs and thus time (especially if you repeat I/O).

Don't use comments unless strictly necessary (reduces readability a lot - crucial if you need others to help debug your code or doing it yourself [may sound counter-intuitive, but you'll be surprized]).

Don't put I/O (getRange(),getValue()) in loops unless having no choice - input / output is always slow, so it is usually better to load everything into memory and work on data there.

Keep consistent scope: if you declare a variable, every accessor should be either in the same scope or nested (e.g. don't declare two vars of the same name inside if...else, move it to outer scope).

Use TypeScript or at least JSDoc - will keep you from going insane while trying to understand why your function expected one type and received another (just as in your case) [UPD: I've also added JSDOC comments to solution].

I've applied a few optimizations to your script, take a look (please, check before using, since we don't have sample data, I couldn't test it). There is a lot more you can do (especially regarding the loop in calcsOnColumns2), but that should be a start:

/**
 * [Your decription here]
 * @returns {Number[]}
 */
function invoicePrice() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var subtotalDisplaySheet = ss.getSheetByName('SubtotalDisplay');

    // define row to do calculations on
    var AVals = subtotalDisplaySheet.getRange("A1:A1000").getValues();
    var ALast = AVals.filter(String).length;

    // Set order No. here
    var orderNoPrev = subtotalDisplaySheet.getRange(ALast - 1, 3).getValue();
    var orderNo = subtotalDisplaySheet.getRange(ALast, 3).setValue(orderNoPrev + 1);

    // invoicePrice the total number of items
    var itemRange = subtotalDisplaySheet.getRange(ALast, 4, 1, 14).getValues()[0];

    // set the values of the constants on the Products page
    var productsSheet = ss.getSheetByName("Products");

    var priceRange = productsSheet.getRange("F1:F1000").getValues();
    var pLast = priceRange.filter(String).length;
    var pGrab = priceRange.splice(0, pLast);

    var outputInvoicePrice = 0;

    var weightRange = productsSheet.getRange("V1:V1000").getValues();
    var wLast = weightRange.filter(String).length;
    var wGrab = weightRange.splice(0, wLast);

    var orderAmounts = subtotalDisplaySheet.getRange(Alast, 17).getValues();

    var total = 0;
    for (var i = 0, len = 13; i <= len; i++) {
        var nextI = i + 1;

        var orderAmount = orderAmounts[0][i + 4];

        total += orderAmount;

        var perKGInvoice = pGrab[nextI].map(Number);
        var weights = wGrab[nextI].map(Number);

        var casePrice = perKGInvoice * weights;

        outputInvoicePrice += orderAmount * casePrice;
    }

    Logger.log(outputInvoicePrice, ALast, pGrab, wGrab);
    return [outputInvoicePrice, ALast, pGrab, wGrab];
}

/**
 * Gets values from 5 rows in
 * a column starting from row 3
 * @param {Sheet} sheet
 * @param {Number} column
 * @returns {*[]}
 */
function getGridValues(sheet, column) {
    var range = sheet.getRange(3, column, 5, 1);
    return range
        .getValues()
        .map(function (row) {
            return row[0];
        });
}

/**
 * [Your decription here]
 * @returns {Number[]}
 */
function tiers() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var discountGridSheet = ss.getSheetByName("DiscountGrid");

    var invoicePriceCall = invoicePrice();
    var outputInvoicePrice = invoicePriceCall[0];
    var ALast = invoicePriceCall[1];

    var beefDiscount = 0;
    var sfDiscount = 0;
    var currentTier = "";

    var tierValues = getGridValues(discountGridSheet, 3);
    var tier1 = tierValues[0];
    var tier2 = tierValues[1];
    var tier3 = tierValues[2];
    var tier4 = tierValues[3];
    var tier5 = tierValues[4];

    var minNotmet = discountGridSheet.getRange(10, 3).getValue();

    var tierBeefDiscountValues = getGridValues(discountGridSheet, 4);
    var tier1BeefDiscount = tierBeefDiscountValues[0];
    var tier2BeefDiscount = tierBeefDiscountValues[1];
    var tier3BeefDiscount = tierBeefDiscountValues[2];
    var tier4BeefDiscount = tierBeefDiscountValues[3];
    var tier5BeefDiscount = tierBeefDiscountValues[4];

    var tierSfDiscountValues = getGridValues(discountGridSheet, 5);
    var tier1SfDiscount = tierSfDiscountValues[0];
    var tier2SfDiscount = tierSfDiscountValues[1];
    var tier3SfDiscount = tierSfDiscountValues[2];
    var tier4SfDiscount = tierSfDiscountValues[3];
    var tier5SfDiscount = tierSfDiscountValues[4];

    if (outputInvoicePrice < tier1) {
        beefDiscount = tier1BeefDiscount;
        sfDiscount = tier1SfDiscount;
        currentTier = "Minimum Not Met";
    }
    else if (outputInvoicePrice < tier2) {
        beefDiscount = tier1BeefDiscount;
        sfDiscount = tier1SfDiscount;
        currentTier = "Tier 1";
    }
    else if (outputInvoicePrice < tier3) {
        beefDiscount = tier2BeefDiscount;
        sfDiscount = tier2SfDiscount;
        currentTier = "Tier 2";
    }
    else if (outputInvoicePrice < tier4) {
        beefDiscount = tier3BeefDiscount;
        sfDiscount = tier3SfDiscount;
        currentTier = "Tier 3";
    }
    else if (outputInvoicePrice < tier5) {
        beefDiscount = tier4BeefDiscount;
        sfDiscount = tier4SfDiscount;
        currentTier = "Tier 4";
    }
    else {
        beefDiscount = tier5BeefDiscount;
        sfDiscount = tier5SfDiscount;
        currentTier = "Tier 5";
    }

    var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay");
    var subtotalDisplayRange = subtotalDisplaySheet.getRange(ALast, 20, 3, 1);
    subtotalDisplayRange.setValues([
        [beefDiscount],
        [sfDiscount],
        [currentTier]
    ]);

    return [beefDiscount, sfDiscount, tier1];
}

/**
 * Foramts amount string
 * @param {Number} amount
 * @returns {Function}
 */
function formatAmount(amount) {
    return function (discount, caseOrder) {
        return amount + " cases @" + discount.toFixed(2) + "/kg = ~$" + caseOrder.toFixed(2);
    };
}

/**
 * Counts sum by discount, amount and weights
 * @param {Number} amount
 * @param {Number} weights
 * @returns {Number}
 */
function countSum(amount, weights) {
    return function (discount) {
        return discount * amount * weights;
    };
}

/**
 * Counts discount case per Kg
 * @param {Number} perKG
 * @returns {Number}
 */
function countDiscountCase(perKG) {
    return function (discount) {
        return perKG - (perKG * discount);
    };
}

/**
 * [Your decription here]
 */
function calcsOnColumns2() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var subtotalDisplaySheet = ss.getSheetByName("SubtotalDisplay");

    var invoicePriceCall = invoicePrice();
    var outputInvoicePrice = invoicePriceCall[0];
    var ALast = invoicePriceCall[1];
    var priceRange = invoicePriceCall[2];
    var weightRange = invoicePriceCall[3];

    var tiers = tiers();
    var beefDiscount = tiers[0];
    var sfDiscount = tiers[1];
    var tier1 = tiers[2];

    var beefSum = 0;
    var sfSum = 0;

    var orderAmounts = subtotalDisplaySheet.getRange(ALast, 17).getValues();

    for (var i = 0, len = 13; i <= len; i++) {
        var orderAmount = orderAmounts[0][i + 4];

        var nextI = i + 1;

        var perKGInvoice = priceRange[nextI].map(Number);
        var weights = weightRange[nextI].map(Number);

        var casePrice = perKGInvoice * weights;

        var subtotalRange = subtotalDisplaySheet.getRange(ALast, i + 32);

        var formatAmountOrder = formatAmount(orderAmount);
        var countDisountSum = countSum(orderAmount, weights);
        var countPerKGCase = countDiscountCase(perKGInvoice);

        // Split up seafood and beef with if statement:
        if (i < 9) {
            var discountCaseBeef = countPerKGCase(beefDiscount);
            var beefCaseOrder = countDisountSum(discountCaseBeef);
            beefSum += beefCaseOrder;
        } else {
            var discountCaseSF = countPerKGCase(sfDiscount);
            var sfCaseOrder = countDisountSum(discountCaseSF);
            sfSum += sfCaseOrder;
        }

        if (orderAmount) {
            subtotalRange.setValue(
                i < 9 ?
                    formatAmountOrder(discountCaseBeef, beefCaseOrder) :
                    formatAmountOrder(discountCaseSF, sfCaseOrder)
            );
        }

        if (i == len) {
            subtotalDisplaySheet.getRange(ALast, 24).setValue(beefSum);
            subtotalDisplaySheet.getRange(ALast, 25).setValue(sfSum);
            // if statement to go here if min order size not met

            var subtotalRange = subtotalDisplaySheet.getRange(ALast, 27);

            var sumOfSums = beefSum + sfSum;

            subtotalRange.setValue(sumOfSums > tier1 ? "Minimum order size not met" : sumOfSums);

            var totalDiscount = outputInvoicePrice - sumOfSums;

            subtotalDisplaySheet.getRange(ALast, 29).setValue(totalDiscount);
            subtotalDisplaySheet.getRange(ALast, 30).setValue(outputInvoicePrice);
        }
    }

}

Notes

Although modern JavaScript will help you avoid the issue, you should
never override any variable names unless you know exactly why you
are doing that (i++ is an example, however functional style will
say that even this is problematic).

Never truncate error messages / code when posting on SO for the sake of readability -knowing what exactly happened is invaluable for us to help you (invoicePrice is undefined says so much more).

References

Hoisting in JavaScript


来源: stackexchange

问:
Define `become=yes' per role with Ansible
In my system provisioning with Ansible, I don't want to specify become=yes in every task, so I created the following ansible.cfg in the project main directory, and Ansible automatically runs everything as root:

```<code>[privilege_escalation]
become = True
</code>```

But as the project kept growing, some new roles should not be run as root. I would like to know if it is possible to have some instruction inside the role that all tasks whithin that role should be run as root (eg. something in vars/), instead of the global ansible.cfg solution above!

答:
Not really a fundamentally different answer, rather a cosmetic reformatting of what's already been said. Looks the shortest, cleanest and YAML-ishest to me:

```<code>- name: My play
  hosts: myhosts
  roles:
    - role: role1
      become: yes

    - role: role2
</code>```

Role1 will be run as root while role2 won't.

ContentLicense: CC BY-SA 3.0

Body:
In my system provisioning with Ansible, I don't want to specify become=yes in every task, so I created the following ansible.cfg in the project main directory, and Ansible automatically runs everything as root:

[privilege_escalation]
become = True

But as the project kept growing, some new roles should not be run as root. I would like to know if it is possible to have some instruction inside the role that all tasks whithin that role should be run as root (eg. something in vars/), instead of the global ansible.cfg solution above!

Body:
Not really a fundamentally different answer, rather a cosmetic reformatting of what's already been said. Looks the shortest, cleanest and YAML-ishest to me:

- name: My play
  hosts: myhosts
  roles:
    - role: role1
      become: yes

    - role: role2

Role1 will be run as root while role2 won't.

ContentLicense: CC BY-SA 4.0


问:
Typing the client object in feathersJS
I'm following the feathersJS guide, but in TS and React and I've run into a problem trying to type the client object.

I've written the following code from the guide

```<code>import feathers from '@feathersjs/client';
import io from 'socket.io-client';

const socket = io();

const client = feathers();
client.configure(feathers.socketio(socket));

client.configure(feathers.authentication({
    storage: window.localStorage
}));
</code>```

And then a snippet from my top level React file I have and get a type error

```<code>useEffect(() => {
    try {
      return await client.reAuthenticate() // <- type error Property 'reAuthenticate' does not exist on type 'Application<any>'
    }
})
</code>```

I tried typing client as const client: Application = feathers(); but then I just get the type error Property 'reAuthenticate' does not exist on type 'Application<{}>'. How can I type client?

答:
You need to use this @feathersjs/authentication-client library.

Run this commands npm install @feathersjs/authentication-client --save and follow this instruction.

@feathersjs/authentication-client declares reAuthenticate methods for you (see this).

Title: Typing the client object in feathersJS

Body:
I'm following the feathersJS guide, but in TS and React and I've run into a problem trying to type the client object.

I've written the following code from the guide

import feathers from '@feathersjs/client';
import io from 'socket.io-client';

const socket = io();

const client = feathers();
client.configure(feathers.socketio(socket));

client.configure(feathers.authentication({
    storage: window.localStorage
}));

And then a snippet from my top level React file I have and get a type error

useEffect(() => {
    try {
      return await client.reAuthenticate() // <- type error Property 'reAuthenticate' does not exist on type 'Application<any>'
    }
})

I tried typing client as const client: Application = feathers(); but then I just get the type error Property 'reAuthenticate' does not exist on type 'Application<{}>'. How can I type client?


问:
extract value from nested json in apache nifi
i have escaped json dataflow (that drives from ConvertAvroToJSON processor) like this:

```<code>{"data": "{\"created_at\":\"Sun Sep 24 11:10:52 +0000 2017\"}"}
</code>```

and i just need "json" value, like this[after unescapeJson]:

```<code>{"created_at":"Sun Sep 24 11:10:52 +0000 2017"}
</code>```

i tried JoltTransformJSON and EvaluateJsonPath solutions but both of them return me this, with {" and "} at begining and end tail of it :

```<code>{"{"created_at":"Sun Sep 24 11:10:52 +0000 2017"}"}
</code>```

what should i do?

Jolt Spec:

[{   "operation": "shift",   "spec": {
      "data": {
        "*": "&"
      }   } }]

EvaluateJsonPath:

$..*

答:
You need 2 steps. First, extract inner json to your flow content. After that you can access json attributes from this json flow content.

First Step:

Second Step

Flow View

Body:
i have escaped json dataflow (that drives from ConvertAvroToJSON processor) like this:

{"data": "{\"created_at\":\"Sun Sep 24 11:10:52 +0000 2017\"}"}

and i just need "json" value, like this[after unescapeJson]:

{"created_at":"Sun Sep 24 11:10:52 +0000 2017"}

i tried JoltTransformJSON and EvaluateJsonPath solutions but both of them return me this, with {" and "} at begining and end tail of it :

{"{"created_at":"Sun Sep 24 11:10:52 +0000 2017"}"}

what should i do?

Jolt Spec:

[{   "operation": "shift",   "spec": {
      "data": {
        "*": "&"
      }   } }]

EvaluateJsonPath:

$..*


问:
Rest Framework incorrect validation on update using SlugRelatedField
I have successfully used SlugRelatedField to validate relationship with other model in create. However when I use update, it does not validate correctly.

Suppose I have:

```<code>#models.py
class Product(models.Model):
    name = models.CharField()
    amount = models.IntegerField()
    description = models.TextField()

    def __str__(self):
        return "{} XL".format(self.name)

class Query(models.Model):
    name = models.CharField()
    product = models.ForeignKey(Product)
    ...

#serializers.py
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

class QuerySerializer(serializers.ModelSerializer):
    product = serializers.SLugRelatedField(slug_field='name', queryset=Product.objects.all())

    class Meta:
        model = Query
        fields = '__all__'

    def create(self, validated_data):
        product = validated_data.pop('product').name
        ...

    def update(self, instance, validated_data):
        instance.product = validated_data.get('product', instance.product)
        ...
</code>```

When I POST, it gets successful:

```<code>{
    "name": "Query 1",
    "product": "Pants",
    ...
}
</code>```

But when I PATCH, it gets problem and got a response error. I know the __str__ in the model complicates things. However I want to solve it without removing it.

```<code>{
    ...
    "product": "Shirt",
    ...
}
</code>```

Response Error:

```<code>{'product': ['Object with name=Shirt XL does not exist.']}
</code>```

How can I catch validation on update? I tried adding validate to print the data. But why is not printing when updating?

```<code>def validate(self, data):
    print(data)    # Does not print on update
    return data
</code>```

Is there also a way to change it before update to make product = product.name like I did in create?

答:
usually the slug field must be unique , so set a flag unique=True
,
When using SlugRelatedField as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with unique=True either must be some sort of pk or uuid object.

Also you can generate your  own slug and use it

```<code>def generate_slug(n=7):
    return ''.join(string.ascii_uppercase + string.digits) for _ in range(n))
</code>```

Body:
I have successfully used SlugRelatedField to validate relationship with other model in create. However when I use update, it does not validate correctly.

Suppose I have:

#models.py
class Product(models.Model):
    name = models.CharField()
    amount = models.IntegerField()
    description = models.TextField()

    def __str__(self):
        return "{} XL".format(self.name)

class Query(models.Model):
    name = models.CharField()
    product = models.ForeignKey(Product)
    ...

#serializers.py
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

class QuerySerializer(serializers.ModelSerializer):
    product = serializers.SLugRelatedField(slug_field='name', queryset=Product.objects.all())

    class Meta:
        model = Query
        fields = '__all__'

    def create(self, validated_data):
        product = validated_data.pop('product').name
        ...

    def update(self, instance, validated_data):
        instance.product = validated_data.get('product', instance.product)
        ...

When I POST, it gets successful:

{
    "name": "Query 1",
    "product": "Pants",
    ...
}

But when I PATCH, it gets problem and got a response error. I know the __str__ in the model complicates things. However I want to solve it without removing it.

{
    ...
    "product": "Shirt",
    ...
}

Response Error:

{'product': ['Object with name=Shirt XL does not exist.']}

How can I catch validation on update? I tried adding validate to print the data. But why is not printing when updating?

def validate(self, data):
    print(data)    # Does not print on update
    return data

Is there also a way to change it before update to make product = product.name like I did in create?

Body:
usually the slug field must be unique , so set a flag unique=True
,
When using SlugRelatedField as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with unique=True either must be some sort of pk or uuid object.

Also you can generate your  own slug and use it

def generate_slug(n=7):
    return ''.join(string.ascii_uppercase + string.digits) for _ in range(n))


问:
Timezone display in java
I need to display timezone in the following format in my UI.

(GMT -05:00) Eastern Time(US & Canada).

I tried getting the current time and timezone from calendar. But when i tried to get the display name from timezone it just displays as "Eastern time". I am not getting the format mentioned above. Can anyone help.

Following is my code snippet and i am using JDK 1.4.2.

```<code>Calendar c = Calendar.getInstance();
TimeZone tz = c.getTimeZone();
String s = tz.getDisplayName();
</code>```

答:
java.time

Specify a proper time zone name in the format of Region/City, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

```<code>ZoneId z = ZoneId.of( "America/New_York" ) ;
</code>```

Get the standard name of the time zone.

```<code>String outputStandardName = z.toString() ;
</code>```

America/New_York

Get the descriptive display name of the zone.

```<code>String outputDisplayName = z.getDisplayName( TextStyle.FULL_STANDALONE , Locale.US ) ;
</code>```

Eastern Time

Get the offset-from-UTC (a number of hours-minutes-seconds) currently in use by people in that region. Go through the ZoneRules class.

```<code>ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( Instant.now() ) ; // Get current offset.
</code>```

offset.toString(): -05:00

See this code run live at IdeOne.com.

ContentLicense: CC BY-SA 2.5

Title: Timezone display in java

Body:
I need to display timezone in the following format in my UI.

(GMT -05:00) Eastern Time(US & Canada).

I tried getting the current time and timezone from calendar. But when i tried to get the display name from timezone it just displays as "Eastern time". I am not getting the format mentioned above. Can anyone help.

Following is my code snippet and i am using JDK 1.4.2.

Calendar c = Calendar.getInstance();
TimeZone tz = c.getTimeZone();
String s = tz.getDisplayName();

Body:
java.time

Specify a proper time zone name in the format of Region/City, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/New_York" ) ;

Get the standard name of the time zone.

String outputStandardName = z.toString() ;

America/New_York

Get the descriptive display name of the zone.

String outputDisplayName = z.getDisplayName( TextStyle.FULL_STANDALONE , Locale.US ) ;

Eastern Time

Get the offset-from-UTC (a number of hours-minutes-seconds) currently in use by people in that region. Go through the ZoneRules class.

ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( Instant.now() ) ; // Get current offset.

offset.toString(): -05:00

See this code run live at IdeOne.com.


问:
Compiler for Win32 Programs?
I'm going to start learning how to program applications for Windows. I'm not sure what compiler I should use. Right now I'm using the Code::Blocks IDE 10.5 and got used to it and would like to stick to it.

I don't know if I should use the GNU GCC compiler or the MSVC++ 2008 compiler. Is there any reason to pick one over the other when creating a Win32 GUI project?

And how can I tell the compiler/linker to look in the Windows SDK directory instead of it's own directory?

答: I would agree with what most others are saying and would use Visual Studio. As pointed out the express version is free, but if you are a student you should look at the Microsoft DreamSpark program.</p>

Title: Compiler for Win32 Programs?


问:
Fastify response schema with $merge-keyword throws FST_ERR_SCH_BUILD
When adding a response schema to a fastify resource that leverages the $merge keyword, an error

```<code>FST_ERR_SCH_BUILD: Failed building the schema for GET: /, due error undefined unsupported
</code>```

is thrown.

Schema looks like the following, but the same error is thrown using the examples from ajv or fastify.

response: {
        200: {
            $merge: {
                source: {
                    type: 'object',
                    properties: {
                        foo: { type: 'string' }
                    }
                },
                with: {
                    type: 'object',
                    properties: {
                        bar: { type: 'string' }
                    }
                }
            }
        }
    }
```

workaround described in own answer

答:
I have found a workaround for this:
it seems that unlike when using $merge in any other schema, either fastify or ajv require the type keyword to be present on $merge level.

This might be a bug, as it can be deduced from the merged objects and the methodology works when  using $merge for other schemas.

Body:
When adding a response schema to a fastify resource that leverages the $merge keyword, an error

FST_ERR_SCH_BUILD: Failed building the schema for GET: /, due error undefined unsupported

is thrown.

Schema looks like the following, but the same error is thrown using the examples from ajv or fastify.

response: {
        200: {
            $merge: {
                source: {
                    type: 'object',
                    properties: {
                        foo: { type: 'string' }
                    }
                },
                with: {
                    type: 'object',
                    properties: {
                        bar: { type: 'string' }
                    }
                }
            }
        }
    }

workaround described in own answer


问:
AWS SageMaker Training Job not saving model output
I'm running a training job on SageMaker. The job doesn't fully complete and hits the MaxRuntimeInSeconds stopping condition. When the job is stopping, documentation says the artifact will still be saved. I've attached the status progression of my training job below. It looks like the training job finished correctly. However the output S3 folder is empty. Any ideas on what is going wrong here? The training data is located in the same bucket so it should have everything it needs.

答:
From the status progression, it seems that the training image download completed at 15:33 UTC and by that time the stopping condition was initiated based on the MaxRuntimeInSeconds parameter that you have specified. From then, it takes 2 mins (15:33 to 15:35) to save any available model artifact but in your case, the training process did not happen at all. The only thing that was done was downloading the pre-built image(containing the ML algorithm). Please refer the following lines from the documentation which says model being saved is subject to the state the training process is in. May be you can try to increase the MaxRuntimeInSeconds and run the job again. Also, please check MaxWaitTimeInSeconds value that you have set if you have.It must be equal to or greater than MaxRuntimeInSeconds.

Please find the excerpts from AWS documentation :

"The training algorithms provided by Amazon SageMaker automatically
  save the intermediate results of a model training job when possible.
  This attempt to save artifacts is only a best effort case as model
  might not be in a state from which it can be saved. For example, if
  training has just started, the model might not be ready to save."


问:
Add String from textEdit to a QStack
I am trying to capture the contents from textEdit and add it to a QStack. The content I am splitting so to be able to reverse the order of the sentence captured. I already have that part covered, but I want to be able to convert from QStringList to be pushed to the QStack. This is what I have:

```<code>    void notepad::on_actionReversed_Text_triggered()
{

    QString unreversed = ui->textEdit->toPlainText();
    QStringList ready = unreversed.split(QRegExp("(\\s|\\n|\\r)+"), QString::SkipEmptyParts);

    QStack<QString> stack;
    stack.push(ready);

    QString result;

    while (!stack.isEmpty())
    {
        result += stack.pop();
        ui->textEdit->setText(result);
    }

}
</code>```

答:
QStack::push only takes objects of it's template type.

i.e. In your case you must push QString's onto the QStack<QString>, and not a list.

So, iterate the list of strings pushing each one in turn.

```<code>foreach (const QString &str, ready) {
    stack.push(str);
}
</code>```

Something else that is wrong is that you are updating textEdit inside the for loop. You actually want to build up the string in the loop and afterwards update the text.

```<code>QString result;
while (!stack.isEmpty()) {
    result += stack.pop();
}

ui->textEdit->setText(result);
</code>```

An alternate answer could be to do away with the stack and just iterate the QStringList ready in reverse order to build up result string.

Title: Add String from textEdit to a QStack

Body:
I am trying to capture the contents from textEdit and add it to a QStack. The content I am splitting so to be able to reverse the order of the sentence captured. I already have that part covered, but I want to be able to convert from QStringList to be pushed to the QStack. This is what I have:

    void notepad::on_actionReversed_Text_triggered()
{

    QString unreversed = ui->textEdit->toPlainText();
    QStringList ready = unreversed.split(QRegExp("(\\s|\\n|\\r)+"), QString::SkipEmptyParts);

    QStack<QString> stack;
    stack.push(ready);

    QString result;

    while (!stack.isEmpty())
    {
        result += stack.pop();
        ui->textEdit->setText(result);
    }

}

Body:
QStack::push only takes objects of it's template type.

i.e. In your case you must push QString's onto the QStack<QString>, and not a list.

So, iterate the list of strings pushing each one in turn.

foreach (const QString &str, ready) {
    stack.push(str);
}

Something else that is wrong is that you are updating textEdit inside the for loop. You actually want to build up the string in the loop and afterwards update the text.

QString result;
while (!stack.isEmpty()) {
    result += stack.pop();
}

ui->textEdit->setText(result);

An alternate answer could be to do away with the stack and just iterate the QStringList ready in reverse order to build up result string.


问:
Laravel issue on migration
Whenever I make new migrations and trying to migrate it the results I get is this. Even if I try to migrate:refresh and so on. What do you think the problem here? I have also checked my .env file. Thank you!

[Illuminate\Database\QueryException]
  SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists (SQL: create table users (
  id int unsigned not null auto_increment primary key, name varchar(255) not null, email varchar(255) not null,
  password varchar(255) not null, remember_token varchar(100) null, created_at timestamp null, updated_at tim
  estamp null) default character set utf8mb4 collate utf8mb4_unicode_ci)

[PDOException]
  SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists

答:
Use !Schema::hasTable('users'), it will check whether a table already exists in the database or not.

If you don't want to drop already exist tables then it is a good idea.

```<code>if (!Schema::hasTable('users')) {
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}
</code>```

Title: Laravel issue on migration

Body:
Use !Schema::hasTable('users'), it will check whether a table already exists in the database or not.

If you don't want to drop already exist tables then it is a good idea.

if (!Schema::hasTable('users')) {
    Schema::create('users', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}


问:
Autmapper Call method on every property map
I want to call a specific method xyz() on every property mapped by generic mapper configuration. Is this possible?

I am using Automapper v 9. Purpose is to call the method on each property mapped by Automapper to check add remove data at runtime.

```<code>public static IMapper CreateMapper<TSource, TDestination>()
        {
            var config = new MapperConfiguration(
                cfg =>
                {
                    cfg.Advanced.AllowAdditiveTypeMapCreation = true;
                    cfg.AllowNullDestinationValues = true;
                    cfg.AllowNullCollections = true;
                    cfg.CreateMap<TSource, TDestination>()
                    .PreserveReferences()
                });

            config.AssertConfigurationIsValid();

            return config.CreateMapper();
        }
</code>```

答:
Yes, you can call what you want. I already use like this.</p>

```<code>  CreateMap<UserMessage, USER>()
                .ForMember(dest => dest.X, opts => opts.MapFrom(src => src.A!= null ? MessageExtensions.GetCvTitle(src.A) : string.Empty))
                .ForMember(dest => dest.Y, opts => opts.MapFrom(src => MessageExtensions.GetFacultyName(src.B)))
                .ForMember(dest => dest.Z, opts => opts.MapFrom(src => MessageExtensions.GetDepartmentName(src.C)))
                .ForMember(dest => dest.T, opts => opts.MapFrom(src => MessageExtensions.GetProgramName(src.D)))
</code>```

Body:
I want to call a specific method xyz() on every property mapped by generic mapper configuration. Is this possible?

I am using Automapper v 9. Purpose is to call the method on each property mapped by Automapper to check add remove data at runtime.

public static IMapper CreateMapper<TSource, TDestination>()
        {
            var config = new MapperConfiguration(
                cfg =>
                {
                    cfg.Advanced.AllowAdditiveTypeMapCreation = true;
                    cfg.AllowNullDestinationValues = true;
                    cfg.AllowNullCollections = true;
                    cfg.CreateMap<TSource, TDestination>()
                    .PreserveReferences()
                });

            config.AssertConfigurationIsValid();

            return config.CreateMapper();
        }

Body:
Yes, you can call what you want. I already use like this.

  CreateMap<UserMessage, USER>()
                .ForMember(dest => dest.X, opts => opts.MapFrom(src => src.A!= null ? MessageExtensions.GetCvTitle(src.A) : string.Empty))
                .ForMember(dest => dest.Y, opts => opts.MapFrom(src => MessageExtensions.GetFacultyName(src.B)))
                .ForMember(dest => dest.Z, opts => opts.MapFrom(src => MessageExtensions.GetDepartmentName(src.C)))
                .ForMember(dest => dest.T, opts => opts.MapFrom(src => MessageExtensions.GetProgramName(src.D)))


问:
How do I Monitoring Clickhouse instances effectively(GCP)
I want to build some sort of materialized view on the system. merges, metrics, asynchronous_metrics, so I get a time-series view of system health(memory consumption, etc).
How is this possible I tried for the system. merges but all I get are the currently running merges?</p>

答:
You can use following variants:

export metrics via graphite protocol to clickhouse itself:

turn on graphite export https://clickhouse.tech/docs/en/operations/server_settings/settings/#server_settings-graphite

use https://github.com/lomik/graphite-clickhouse for storage exported data back to clickhouse

complete vagrant demo stand here: https://github.com/Slach/clickhouse-metrics-grafana/

use undocumented system.metric_log table

look at https://github.com/ClickHouse/ClickHouse/issues/6363 and https://github.com/ClickHouse/ClickHouse/search?q=metric_log, https://github.com/ClickHouse/ClickHouse/blob/master/dbms/programs/server/config.d/metric_log.xml

turn on system.metric_log in /etc/clickhouse-server/config.d/metric_log.xml

<yandex>
    <metric_log>
        <database>system</database>

metric_log

        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
        <collect_interval_milliseconds>1000</collect_interval_milliseconds>
    </metric_log>
</yandex>```

be careful, according to https://github.com/ClickHouse/ClickHouse/blob/master/dbms/src/Interpreters/MetricLog.cpp#L18 system.asynchronous_metrics doesn't flush into system.metric_log

Body:
You can use following variants:

export metrics via graphite protocol to clickhouse itself:

turn on graphite export https://clickhouse.tech/docs/en/operations/server_settings/settings/#server_settings-graphite

use https://github.com/lomik/graphite-clickhouse for storage exported data back to clickhouse

complete vagrant demo stand here: https://github.com/Slach/clickhouse-metrics-grafana/

use undocumented system.metric_log table

look at https://github.com/ClickHouse/ClickHouse/issues/6363 and https://github.com/ClickHouse/ClickHouse/search?q=metric_log, https://github.com/ClickHouse/ClickHouse/blob/master/dbms/programs/server/config.d/metric_log.xml

turn on system.metric_log in /etc/clickhouse-server/config.d/metric_log.xml

<yandex>
    <metric_log>
        <database>system</database>
        <table>metric_log</table>
        <flush_interval_milliseconds>7500</flush_interval_milliseconds>
        <collect_interval_milliseconds>1000</collect_interval_milliseconds>
    </metric_log>
</yandex>

be careful, according to https://github.com/ClickHouse/ClickHouse/blob/master/dbms/src/Interpreters/MetricLog.cpp#L18 system.asynchronous_metrics doesn't flush into system.metric_log


问:
Anyone know the magic to connect Access 2007 to SQL Server 2008?
I never use Access 2007 - until today.

I want to connect to an existing SQL Server 2008 database. I have tried using:

External Data ODBC option - but get DSN errror

Upsizing wizard with ODBC - get an error

Upsizing wizard with SNAC - get ODBC error. So that one seems a none starter :-)

I have done some searching and only found others with same issue. About to do some more... but hoping one of you has the answer OTTOYH. Thanks.

答: The upsizing wizard in Access 2007 is not aware of SQL Server 2008 and therefore won't connect. You should use the SQL Server migration assistant for Access tool that is provided with SQL Server 2008.</p>

OwnerDisplayName: Eric Nelson

OwnerDisplayName: Quintus Marais


问:
WCF service behaviour on Timeout exception
We have a WCF service method (synchronous), which calls another process (through COM) to do some stuff. Now this COM process takes about 10-15 seconds to complete and then returns the call to my service which in turn should be returned to the client.

On the WCF client side, we have a sendtimeout set as 5 seconds, so after 5 seconds we receive timeout exception in the client.

Now my question is what happens on the service side after the client receives timeout exception. Because the call the COM process is still in progress and may return to service after another 5-10 seconds, how the service handles this scenario.

Let me know if further input is required.

Regards,

答:
Afaik, an exception is thrown on the client side but the service carries on the operation. If you have long running operations, you might check out asynchronous calls.

Update:
If this is not possible and increasing the timeout is not an option by the same reason, I can't see how you can avoid the timeout exception. Some ways to recover:

If you'd like to abort the server operation on client timeout, you might add a service operation like CancelCOMCall, and invoke from the client when it catches a TimeoutException, which would kill the COM process.

If you want to let the operation complete but prevent duplicate calls from the client (caused by retries after timeout exception), you might save which COM operations are running per client and discard calls for already running processes.

I'd agree neither method is very neat, but it looks a little difficult to me without asynchronous calls. I'm not a WCF expert though.


问:
Query a JSON column to extract the selected map in Array List of Mysql 5.7
I'm using Mysql 5.7 and it has following data set.

```<code>mysql> select id, browser from events;

+----+--------------------------------------------------------------------+
| id | browser                                                            |
+----+--------------------------------------------------------------------+
|  1 | [{"price": "10.00", "tag": "60"}, {"price": "25.00", "tag": "20"}] |
|  2 | [{"price": "8.00", "tag": "10"}, {"price": "25.00", "tag": "20 "}] |
+----+--------------------------------------------------------------------+
</code>```

I want to extract only the following map out of this data set. (Not the whole array list)

```<code>{"price": "10.00", "tag": "60"}
</code>```

I tried following command but provide an empty set.

```<code>mysql> select * from events where json_contains(browser->'$[*].price', json_object('price',"10.00"));
Empty set (0.00 sec)
</code>```

Can someone explain me why it is not working or how to query the map contains price =10.00 ?

答:
```<code>SELECT browser,JSON_EXTRACT(browser,"$.price")
FROM events t
WHERE JSON_EXTRACT(browser,"$.price")=10.00
</code>```

Body:
I'm using Mysql 5.7 and it has following data set.

mysql> select id, browser from events;

+----+--------------------------------------------------------------------+
| id | browser                                                            |
+----+--------------------------------------------------------------------+
|  1 | [{"price": "10.00", "tag": "60"}, {"price": "25.00", "tag": "20"}] |
|  2 | [{"price": "8.00", "tag": "10"}, {"price": "25.00", "tag": "20 "}] |
+----+--------------------------------------------------------------------+

I want to extract only the following map out of this data set. (Not the whole array list)

{"price": "10.00", "tag": "60"}

I tried following command but provide an empty set.

mysql> select * from events where json_contains(browser->'$[*].price', json_object('price',"10.00"));
Empty set (0.00 sec)

Can someone explain me why it is not working or how to query the map contains price =10.00 ?


问:
Why Currency.defaultFractionDigits() for IDR is 0 for android?
For Indonesian currency (IDR), defaultFractionDigits() gives me 0 in Android app.

```<code>Locale locale = new Locale("in", "ID");
Currency currency = Currency.getInstance(locale);
Log.d("TEST",String.format(locale, "Currency - %s ( %s )  Decimal - %s ",
        currency.getSymbol(locale),
        currency.getSymbol(),
        currency.getDefaultFractionDigits()));
</code>```

D/TEST: Currency - Rp ( IDR )  Decimal - 0

Same gives me 2 when I'm testing it in my eclipse (also in RexTester)

```<code>Locale.setDefault(new Locale("in","ID"));
Currency c = Currency.getInstance("IDR");
System.out.println("Symbol: " + c.getSymbol());
System.out.println("Default fractional digits: " + c.getDefaultFractionDigits());
</code>```

Symbol: Rp

Default fractional digits: 2

Documentation of both Android & Java states that it's ISO 4217 (ISO 4217:2015 lists the IDR with two-digit decimal points)

Why it's 0 for Android App?

答:
Google seems to have fixed this on android 10, either knowingly or unknowingly.
So, on android 10, Currency's  defaultFractionDigits method will return 2 for IDR, but on android 9 or below, it will keep returning 0.

Becuase of this, the whole functioning of how we format IDR on UI broke, and we had to handle it on client itself    :(

Body:
For Indonesian currency (IDR), defaultFractionDigits() gives me 0 in Android app.

Locale locale = new Locale("in", "ID");
Currency currency = Currency.getInstance(locale);
Log.d("TEST",String.format(locale, "Currency - %s ( %s )  Decimal - %s ",
        currency.getSymbol(locale),
        currency.getSymbol(),
        currency.getDefaultFractionDigits()));

D/TEST: Currency - Rp ( IDR )  Decimal - 0

Same gives me 2 when I'm testing it in my eclipse (also in RexTester)

Locale.setDefault(new Locale("in","ID"));
Currency c = Currency.getInstance("IDR");
System.out.println("Symbol: " + c.getSymbol());
System.out.println("Default fractional digits: " + c.getDefaultFractionDigits());

Symbol: Rp

Default fractional digits: 2

Documentation of both Android & Java states that it's ISO 4217 (ISO 4217:2015 lists the IDR with two-digit decimal points)

Why it's 0 for Android App?


问:
How do I fix a PostgreSQL 9.3 Slave that Cannot Keep Up with the Master?
We have a master-slave replication configuration as follows.

On the master:

postgresql.conf has replication configured as follows (commented line taken out for brevity):

```<code>max_wal_senders = 1
wal_keep_segments = 8
</code>```

On the slave:

Same postgresql.conf as on the master. recovery.conf looks like this:

```<code>standby_mode = 'on'
primary_conninfo = 'host=master1 port=5432 user=replication password=replication'
trigger_file = '/tmp/postgresql.trigger.5432'
</code>```

When this was initially setup, we performed some simple tests and confirmed the replication was working. However, when we did the initial data load, only some of the data made it to the slave.

Slave's log is now filled with messages that look like this:

```<code>< 2015-01-23 23:59:47.241 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:47.241 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:52.259 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:52.260 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:57.270 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:57.270 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed
</code>```

After some analysis and help on the #postgresql IRC channel, I've come to the conclusion that the slave cannot keep up with the master. My proposed solution is as follows.

On the master:

Set max_wal_senders=5

Set wal_keep_segments=4000 . Yes I know it is very high, but I'd like to monitor the situation and see what happens. I have room on the master.

On the slave:

Save configuration files in the data directory (i.e. pg_hba.conf  pg_ident.conf  postgresql.conf  recovery.conf)

Clear out the data directory (rm -rf /var/lib/pgsql/9.3/data/*) . This seems to be required by pg_basebackup.

Run the following command:
pg_basebackup -h master -D /var/lib/pgsql/9.3/data  --username=replication --password

Am I missing anything ? Is there a better way to bring the slave up-to-date w/o having to reload all the data ?

Any help is greatly appreciated.

答:
You will get that error if keep_wal_segments setting is too low.
When you set the value for keep_wal_segments consider that "How long is the pg_basebackup taking?"

Remember that segments are generated about every 5 minutes, so if the backup takes an hour, you need at least 12 segments saved. At 2 hours, you need 24, etc. I would set the value to about 12.2 segments/hour of backup.

Body:
We have a master-slave replication configuration as follows.

On the master:

postgresql.conf has replication configured as follows (commented line taken out for brevity):

max_wal_senders = 1
wal_keep_segments = 8

On the slave:

Same postgresql.conf as on the master. recovery.conf looks like this:

standby_mode = 'on'
primary_conninfo = 'host=master1 port=5432 user=replication password=replication'
trigger_file = '/tmp/postgresql.trigger.5432'

When this was initially setup, we performed some simple tests and confirmed the replication was working. However, when we did the initial data load, only some of the data made it to the slave.

Slave's log is now filled with messages that look like this:

< 2015-01-23 23:59:47.241 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:47.241 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:52.259 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:52.260 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:57.270 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:57.270 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

After some analysis and help on the #postgresql IRC channel, I've come to the conclusion that the slave cannot keep up with the master. My proposed solution is as follows.

On the master:

Set max_wal_senders=5

Set wal_keep_segments=4000 . Yes I know it is very high, but I'd like to monitor the situation and see what happens. I have room on the master.

On the slave:

Save configuration files in the data directory (i.e. pg_hba.conf  pg_ident.conf  postgresql.conf  recovery.conf)

Clear out the data directory (rm -rf /var/lib/pgsql/9.3/data/*) . This seems to be required by pg_basebackup.

Run the following command:
pg_basebackup -h master -D /var/lib/pgsql/9.3/data  --username=replication --password

Am I missing anything ? Is there a better way to bring the slave up-to-date w/o having to reload all the data ?

Any help is greatly appreciated.


问:
Typing a mapShape function in TypeScript
I want to use a utility function like this:

```<code>const out = mapShape(
  { foo: 1, bar: '2', baz: 'hello' },
  { foo: x => String(x), bar: x => parseInt(x) }
)
// outputs { foo: '1', bar: 2 }
</code>```

Is there a way to parameterize it in TypeScript so that the type of the output will be this?

```<code>{ foo: string, bar: number }
</code>```

I tried doing this:

```<code>export default function mapShape<
  I extends Record<any, any>,
  X extends { [K in keyof I]: (value: I[K], key: K, object: I) => any }
>(
  object: I,
  mapper: Partial<X>
): {
  [K in keyof I]: ReturnType<X[K]>
} {
  const result: any = {}
  for (const key in mapper) {
    if (Object.hasOwnProperty.call(mapper, key)) {
      result[key] = (mapper[key] as any)(object[key], key, object)
    }
  }
  return result
}
</code>```

However type TS infers for out is { foo: any, bar: any }; it doesn't infer specific types for the properties.

The following produces the correct output type, I'm just not sure if I can parameterize it:

```<code>const mappers = {
  foo: x => String(x),
  bar: x => parseInt(x),
}
type outputType = {
  [K in keyof typeof mappers]: ReturnType<typeof mappers[K]>
}
// { foo: string, bar: number }
</code>```

答:
After experimenting with @jcalz' answer, I got the following lodash/fp style version to work:

```<code>export default function mapShape<U extends Record<any, (...args: any) => any>>(
  mapper: U
): <T extends { [K in keyof U]?: any }>(
  obj: {
    [K in keyof T]?: K extends keyof U ? Parameters<U[K]>[0] : any
  }
) => { [K in keyof U]: ReturnType<U[K]> } {
  return (obj: any) => {
    const result: any = {}
    for (const key in mapper) {
      if (Object.hasOwnProperty.call(mapper, key)) {
        result[key] = mapper[key](obj[key], key, obj)
      }
    }
    return result
  }
}

mapShape({
  foo: (x: number) => String(x),
  bar: (x: string) => parseInt(x),
})({
  foo: 1,
  bar: '2',
  baz: 'hello',
})
</code>```

Body:
I want to use a utility function like this:

const out = mapShape(
  { foo: 1, bar: '2', baz: 'hello' },
  { foo: x => String(x), bar: x => parseInt(x) }
)
// outputs { foo: '1', bar: 2 }

Is there a way to parameterize it in TypeScript so that the type of the output will be this?

{ foo: string, bar: number }

I tried doing this:

export default function mapShape<
  I extends Record<any, any>,
  X extends { [K in keyof I]: (value: I[K], key: K, object: I) => any }
>(
  object: I,
  mapper: Partial<X>
): {
  [K in keyof I]: ReturnType<X[K]>
} {
  const result: any = {}
  for (const key in mapper) {
    if (Object.hasOwnProperty.call(mapper, key)) {
      result[key] = (mapper[key] as any)(object[key], key, object)
    }
  }
  return result
}

However type TS infers for out is { foo: any, bar: any }; it doesn't infer specific types for the properties.

The following produces the correct output type, I'm just not sure if I can parameterize it:

const mappers = {
  foo: x => String(x),
  bar: x => parseInt(x),
}
type outputType = {
  [K in keyof typeof mappers]: ReturnType<typeof mappers[K]>
}
// { foo: string, bar: number }

Body:
After experimenting with @jcalz' answer, I got the following lodash/fp style version to work:

export default function mapShape<U extends Record<any, (...args: any) => any>>(
  mapper: U
): <T extends { [K in keyof U]?: any }>(
  obj: {
    [K in keyof T]?: K extends keyof U ? Parameters<U[K]>[0] : any
  }
) => { [K in keyof U]: ReturnType<U[K]> } {
  return (obj: any) => {
    const result: any = {}
    for (const key in mapper) {
      if (Object.hasOwnProperty.call(mapper, key)) {
        result[key] = mapper[key](obj[key], key, obj)
      }
    }
    return result
  }
}

mapShape({
  foo: (x: number) => String(x),
  bar: (x: string) => parseInt(x),
})({
  foo: 1,
  bar: '2',
  baz: 'hello',
})


问:
What happens with ActiveMQ unacknowledged messages
If there's a queue created in ActiveMQ which has one producer (which is client acknowledged mode) and one listener in whose onMessage method after successful processing of message only it is acknowledged. Say if there is an exception and the message remains unacknowledged and hence remains in the queue. Will it be sent again to consumer? Or what happens to such messages?</p>

答:
All unacknowledged messages remain in the queue.

Will it be sent again to consumer?

Yes, it will be sent to consumer again.

I am not sure if Active MQ has a queue property which when set will stop delivering the same message to consumer again and again and instead move it to a queue called backout queue or a dead letter queue. IBM MQ has a property on queue, BOTHRESH - Backout Threshold - Every time a message is delivered to consumer, the delivery count (or Backout Count) is incremented. When the message is being delivered again, IBM MQ will check if the backout count of the message is more than BOTHRESH count. If so the message is moved to a backout queue if one is set or to a dead letter queue.


问:
Regex for ESI Number
I need a regex in C# for below mentioned number

```<code>31–00–123456–000–0001
</code>```

I am having a problem putting the dash in the regex. The number validation is pretty fine.

答:
If any kind of dash (e.g. U+02013) are acceptable, I suggest using \p{Pd} which means any unicode dash (Punctuation dash). In case the digits should be separated by any dash, which, however, must be the same within the entire string:

```<code>Regex regex = new Regex(@"^[0-9]{2}(\p{Pd})[0-9]{2}\1[0-9]{6}\1[0-9]{3}\1[0-9]{4}$");
</code>```

Demo:

```<code>  string[] tests = new string[] {
    "31–00–123456–000–0001", // All Dashes
    "31-00-123456-000-0001", // All minuses
    "31–00-123456-000-0001", // Dash then minues
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,25} :: {(regex.IsMatch(test) ? "Matched" : "Failed")}"));

  Console.Write(report);
</code>```

Outcome:

```<code>31–00–123456–000–0001 :: Matched
31-00-123456-000-0001 :: Matched
31–00-123456-000-0001 :: Failed
</code>```

If you want to tolerate diffrent dashes within the same string:

```<code>Regex regex = new Regex(
  @"^[0-9]{2}\p{Pd}[0-9]{2}\p{Pd}[0-9]{6}\p{Pd}[0-9]{3}\p{Pd}[0-9]{4}$");
</code>```

Title: Regex for ESI Number

Body:
I need a regex in C# for below mentioned number

31–00–123456–000–0001

I am having a problem putting the dash in the regex. The number validation is pretty fine.

Body:
If any kind of dash (e.g. U+02013) are acceptable, I suggest using \p{Pd} which means any unicode dash (Punctuation dash). In case the digits should be separated by any dash, which, however, must be the same within the entire string:

Regex regex = new Regex(@"^[0-9]{2}(\p{Pd})[0-9]{2}\1[0-9]{6}\1[0-9]{3}\1[0-9]{4}$");

Demo:

  string[] tests = new string[] {
    "31–00–123456–000–0001", // All Dashes
    "31-00-123456-000-0001", // All minuses
    "31–00-123456-000-0001", // Dash then minues
  };

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,25} :: {(regex.IsMatch(test) ? "Matched" : "Failed")}"));

  Console.Write(report);

Outcome:

31–00–123456–000–0001 :: Matched
31-00-123456-000-0001 :: Matched
31–00-123456-000-0001 :: Failed

If you want to tolerate diffrent dashes within the same string:

Regex regex = new Regex(
  @"^[0-9]{2}\p{Pd}[0-9]{2}\p{Pd}[0-9]{6}\p{Pd}[0-9]{3}\p{Pd}[0-9]{4}$");


问:
How to allow access outside localhost
How can I allow access outside the localhost at Angular2? I can navigate at localhost:3030/panel easily but I can not navigate when I write my IP such as 10.123.14.12:3030/panel/.

Could you please allow me how to fix it? I am not using npm (node project manage - node install/node start ) to install and run the project.

If you want, I can provide my package.json and index.html.

答:
A quick solution that might help someone :

Add this line as value for start ng serve --host 0.0.0.0 --disable-host-check
in your package.json

ex:

```<code>{
"ng": "ng",
"start": "ng serve --host 0.0.0.0 --disable-host-check",
"build": "ng build",
}
</code>```

And then simply do start or npm run start

you will be able to access your project from other local IPs.

Title: How to allow access outside localhost

Body:
A quick solution that might help someone :

Add this line as value for start ng serve --host 0.0.0.0 --disable-host-check
in your package.json

ex:

{
"ng": "ng",
"start": "ng serve --host 0.0.0.0 --disable-host-check",
"build": "ng build",
}

And then simply do start or npm run start

you will be able to access your project from other local IPs.


问:
Azure Resource Manager template chained functions
I am trying to remove / from the URL using azure function before assigning to output variable value

```<code>"webappStorageUri":{
      "type": "string",
      "value": "[take(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web, length(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web)-1]"
 }
</code>```

Returned value from length function should be the value for take function. This is not working. I get following error on deployment. I don't get anything out of this error message. Does Azure support chained function execution? Is this is right approach to remove / from the URL?

Error message

```<code>[error]Deployment template language expression evaluation failed: 'Unable to parse language expression 'take(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web, length(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web)-1': expected token 'RightParenthesis' and actual 'Integer'.'. Please see https://aka.ms/arm-template-expressions for usage details.
</code>```

答:
I'm not sure what you are trying to achieve, but your function has issues with brackets, and you cannot really substract by appending -1 in a random place.

```<code>"[take(reference(variables('webappStorageName')).primaryEndpoints.web,
    sub(length(reference(variables('webappStorageName')).primaryEndpoints.web), 1))]"
</code>```

line breaks for readability only

Body:
I am trying to remove / from the URL using azure function before assigning to output variable value

"webappStorageUri":{
      "type": "string",
      "value": "[take(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web, length(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web)-1]"
 }

Returned value from length function should be the value for take function. This is not working. I get following error on deployment. I don't get anything out of this error message. Does Azure support chained function execution? Is this is right approach to remove / from the URL?

Error message

[error]Deployment template language expression evaluation failed: 'Unable to parse language expression 'take(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web, length(reference(resourceId('Microsoft.Storage/storageAccounts', variables('webappStorageName'))).primaryEndpoints.web)-1': expected token 'RightParenthesis' and actual 'Integer'.'. Please see https://aka.ms/arm-template-expressions for usage details.

Body:
I'm not sure what you are trying to achieve, but your function has issues with brackets, and you cannot really substract by appending -1 in a random place.

"[take(reference(variables('webappStorageName')).primaryEndpoints.web,
    sub(length(reference(variables('webappStorageName')).primaryEndpoints.web), 1))]"

line breaks for readability only


问:
Group wise count in SQL Server
Trying to get groupwise count based on shipmentId.

```<code>SELECT
    shipment_inventory.shipmentlocation containerNumber,
    shipment_master.shipmentid shipmentId,
    shipment_houseinformation.receptaclenumber,
    shipment_houseinformation.lastbagindicator
FROM
    imp_breakdownuldtrolleyinfo
INNER JOIN
    imp_shipmentverification ON imp_breakdownuldtrolleyinfo.impshipmentverificationid = imp_shipmentverification.impshipmentverificationid
INNER JOIN
    shipment_master ON imp_shipmentverification.shipmentid = shipment_master.shipmentid
INNER JOIN
    shipment_houseinformation ON shipment_master.shipmentid = shipment_houseinformation.shipmentid
INNER JOIN
    shipment_inventory ON shipment_master.shipmentid = shipment_inventory.shipment_id
WHERE
    shipment_inventory.shipmentlocation = 'AKE21192SQ'
    AND shipment_master.shipmenttype = 'MAIL'
ORDER BY
    shipment_master.shipmentnumber,
    shipment_houseinformation.receptaclenumber
</code>```

Current result:

```<code>containerNumber shipmentId  ReceptacleNumber    LastBagIndicator
----------------------------------------------------------------
AKE21192SQ          151811      001                 0
AKE21192SQ          151811      002                 1
AKE21192SQ          151810      001                 0
AKE21192SQ          151810      002                 0
AKE21192SQ          151810      003                 1
</code>```

Expected result:

```<code>containerNumber shipmentId  ReceptacleNumber    LastBagIndicator shipmentIdCount
AKE21192SQ          151811      001                 0             2
AKE21192SQ          151811      002                 1             2
AKE21192SQ          151810      001                 0             3
AKE21192SQ          151810      002                 0             3
AKE21192SQ          151810      003                 1             3
</code>```

Can anybody explain how I can achieve the expected result?

答:
You can use PARTITION BY shipmentId like following to get the count.

```<code>SELECT shipment_inventory.shipmentlocation containerNumber,
       shipment_master.shipmentid shipmentId,
       shipment_houseinformation.receptaclenumber,
       shipment_houseinformation.lastbagindicator,
       count(*) over(partition by shipmentId ) as  shipmentIdCount
FROM   imp_breakdownuldtrolleyinfo
       INNER JOIN imp_shipmentverification
               ON imp_breakdownuldtrolleyinfo.impshipmentverificationid =
                  imp_shipmentverification.impshipmentverificationid
       INNER JOIN shipment_master
               ON imp_shipmentverification.shipmentid =
                  shipment_master.shipmentid
       INNER JOIN shipment_houseinformation
               ON shipment_master.shipmentid =
                  shipment_houseinformation.shipmentid
       INNER JOIN shipment_inventory
               ON shipment_master.shipmentid = shipment_inventory.shipment_id
WHERE  shipment_inventory.shipmentlocation = 'AKE21192SQ'
       AND shipment_master.shipmenttype = 'MAIL'
ORDER  BY shipment_master.shipmentnumber,
          shipment_houseinformation.receptaclenumber
</code>```

Title: Group wise count in SQL Server

Body:
Trying to get groupwise count based on shipmentId.

SELECT
    shipment_inventory.shipmentlocation containerNumber,
    shipment_master.shipmentid shipmentId,
    shipment_houseinformation.receptaclenumber,
    shipment_houseinformation.lastbagindicator
FROM
    imp_breakdownuldtrolleyinfo
INNER JOIN
    imp_shipmentverification ON imp_breakdownuldtrolleyinfo.impshipmentverificationid = imp_shipmentverification.impshipmentverificationid
INNER JOIN
    shipment_master ON imp_shipmentverification.shipmentid = shipment_master.shipmentid
INNER JOIN
    shipment_houseinformation ON shipment_master.shipmentid = shipment_houseinformation.shipmentid
INNER JOIN
    shipment_inventory ON shipment_master.shipmentid = shipment_inventory.shipment_id
WHERE
    shipment_inventory.shipmentlocation = 'AKE21192SQ'
    AND shipment_master.shipmenttype = 'MAIL'
ORDER BY
    shipment_master.shipmentnumber,
    shipment_houseinformation.receptaclenumber

Current result:

containerNumber shipmentId  ReceptacleNumber    LastBagIndicator
----------------------------------------------------------------
AKE21192SQ          151811      001                 0
AKE21192SQ          151811      002                 1
AKE21192SQ          151810      001                 0
AKE21192SQ          151810      002                 0
AKE21192SQ          151810      003                 1

Expected result:

containerNumber shipmentId  ReceptacleNumber    LastBagIndicator shipmentIdCount
AKE21192SQ          151811      001                 0             2
AKE21192SQ          151811      002                 1             2
AKE21192SQ          151810      001                 0             3
AKE21192SQ          151810      002                 0             3
AKE21192SQ          151810      003                 1             3

Can anybody explain how I can achieve the expected result?

Body:
You can use PARTITION BY shipmentId like following to get the count.

SELECT shipment_inventory.shipmentlocation containerNumber,
       shipment_master.shipmentid shipmentId,
       shipment_houseinformation.receptaclenumber,
       shipment_houseinformation.lastbagindicator,
       count(*) over(partition by shipmentId ) as  shipmentIdCount
FROM   imp_breakdownuldtrolleyinfo
       INNER JOIN imp_shipmentverification
               ON imp_breakdownuldtrolleyinfo.impshipmentverificationid =
                  imp_shipmentverification.impshipmentverificationid
       INNER JOIN shipment_master
               ON imp_shipmentverification.shipmentid =
                  shipment_master.shipmentid
       INNER JOIN shipment_houseinformation
               ON shipment_master.shipmentid =
                  shipment_houseinformation.shipmentid
       INNER JOIN shipment_inventory
               ON shipment_master.shipmentid = shipment_inventory.shipment_id
WHERE  shipment_inventory.shipmentlocation = 'AKE21192SQ'
       AND shipment_master.shipmenttype = 'MAIL'
ORDER  BY shipment_master.shipmentnumber,
          shipment_houseinformation.receptaclenumber