<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://izara.io/wiki/index.php?action=history&amp;feed=atom&amp;title=SQS_DSQ_Hdr</id>
	<title>SQS DSQ Hdr - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://izara.io/wiki/index.php?action=history&amp;feed=atom&amp;title=SQS_DSQ_Hdr"/>
	<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=SQS_DSQ_Hdr&amp;action=history"/>
	<updated>2026-06-23T12:09:42Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://izara.io/wiki/index.php?title=SQS_DSQ_Hdr&amp;diff=2559&amp;oldid=prev</id>
		<title>Praew: Created page with &quot;= Example Sqs|Dsq Handler = step for create lambdaFunction and Sqs|Dsq handler == Lambda == * add lambda, copy LambdaFunction.js and change name, ex: ProcessProduct_Main.js &lt;syntaxhighlight lang=&quot;JavaScript&quot;&gt; &#039;use strict&#039;;  const izaraSharedLib = require(&#039;@izara_project/izara-shared&#039;); const dynamodbSharedLib = izaraSharedLib.dynamodbSharedLib;  const hash = require(&#039;object-hash&#039;);  //* require more module that you use   /**  * description of function.  * @param {string}...&quot;</title>
		<link rel="alternate" type="text/html" href="https://izara.io/wiki/index.php?title=SQS_DSQ_Hdr&amp;diff=2559&amp;oldid=prev"/>
		<updated>2023-10-19T04:42:30Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= Example Sqs|Dsq Handler = step for create lambdaFunction and Sqs|Dsq handler == Lambda == * add lambda, copy LambdaFunction.js and change name, ex: ProcessProduct_Main.js &amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt; &amp;#039;use strict&amp;#039;;  const izaraSharedLib = require(&amp;#039;@izara_project/izara-shared&amp;#039;); const dynamodbSharedLib = izaraSharedLib.dynamodbSharedLib;  const hash = require(&amp;#039;object-hash&amp;#039;);  //* require more module that you use   /**  * description of function.  * @param {string}...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Example Sqs|Dsq Handler =&lt;br /&gt;
step for create lambdaFunction and Sqs|Dsq handler&lt;br /&gt;
== Lambda ==&lt;br /&gt;
* add lambda, copy LambdaFunction.js and change name, ex: ProcessProduct_Main.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;#039;use strict&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
const izaraSharedLib = require(&amp;#039;@izara_project/izara-shared&amp;#039;);&lt;br /&gt;
const dynamodbSharedLib = izaraSharedLib.dynamodbSharedLib;&lt;br /&gt;
&lt;br /&gt;
const hash = require(&amp;#039;object-hash&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
//* require more module that you use&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * description of function.&lt;br /&gt;
 * @param {string} productId&lt;br /&gt;
 *&lt;br /&gt;
 * @returns {string} dataName&lt;br /&gt;
 */&lt;br /&gt;
module.exports.processProduct = async (&lt;br /&gt;
  _izContext,&lt;br /&gt;
  productId&lt;br /&gt;
) =&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
try {&lt;br /&gt;
    _izContext.logger.debug(&amp;#039;ProcessProduct: &amp;#039;, {&lt;br /&gt;
      productId&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    // ... do something&lt;br /&gt;
&lt;br /&gt;
    //* get item of productId from table&lt;br /&gt;
    let productRecord = await dynamodbSharedLib.getItem(&lt;br /&gt;
      _izContext,&lt;br /&gt;
      {&lt;br /&gt;
        //your keyValue&lt;br /&gt;
      }&lt;br /&gt;
    );&lt;br /&gt;
    _izContext.logger.debug(&amp;quot;productRecord: &amp;quot;, productRecord);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    //* check record&lt;br /&gt;
      //* if no record =&amp;gt; throw error&lt;br /&gt;
      //* have record =&amp;gt; get type and name from record =&amp;gt; dataName = type + &amp;quot;_&amp;quot; + name&lt;br /&gt;
    if (!productRecord) {&lt;br /&gt;
      //throw error;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let dataName = type + &amp;quot;_&amp;quot; + name;&lt;br /&gt;
     _izContext.logger.debug(&amp;quot;dataName: &amp;quot;, dataName);&lt;br /&gt;
&lt;br /&gt;
    // send message to SNS OutProductComplete&lt;br /&gt;
     let productRequest = {&lt;br /&gt;
       Message: JSON.stringify({&lt;br /&gt;
         dataName: dataName,&lt;br /&gt;
       }),&lt;br /&gt;
       TopicArn: snsSharedLib.snsTopicArn(&amp;#039;OutProductComplete&amp;#039;)&lt;br /&gt;
     };&lt;br /&gt;
&lt;br /&gt;
     _izContext.logger.debug(&amp;quot;RequestParams before send to sqs OutProductComplete &amp;quot;, productRequest);&lt;br /&gt;
     await sns.publishAsync(_izContext, productRequest);&lt;br /&gt;
&lt;br /&gt;
    return &amp;quot;product complete&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  } catch (err) {&lt;br /&gt;
    _izContext.logger.error(&amp;#039;error ProcessProduct: &amp;#039;, err)&lt;br /&gt;
    throw (err)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Local testing&lt;br /&gt;
async function test() {&lt;br /&gt;
&lt;br /&gt;
  const CorrelationIds = require(&amp;#039;@izara_project/izara-core-library-correlation-ids&amp;#039;);&lt;br /&gt;
  const Logger = require(&amp;#039;@izara_project/izara-core-library-logger&amp;#039;);&lt;br /&gt;
  const IntegrationTestDetail = require(&amp;#039;@izara_project/izara-core-library-integration-tests/src/IntegrationTests&amp;#039;)&lt;br /&gt;
  let _izContext = {&lt;br /&gt;
    correlationIds: CorrelationIds,&lt;br /&gt;
    logger: Logger,&lt;br /&gt;
    integrationTestDetail: IntegrationTestDetail&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  let productId = &amp;quot;hashOfTypeAndNameEqualsProductId&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  return module.exports.updateCatalogSettings(&lt;br /&gt;
    _izContext,&lt;br /&gt;
    productId&lt;br /&gt;
  )&lt;br /&gt;
}&lt;br /&gt;
test();&lt;br /&gt;
&lt;br /&gt;
** node ProcessProduct_Main.js =&amp;gt; in terminal&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* add lambda handler, copy LambdaFunctionHdrSqs.js and change name, ex: ProcessProduct_HdrSqs.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;JavaScript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;#039;use strict&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
const izara = require(&amp;quot;@izara_project/izara-middleware&amp;quot;);&lt;br /&gt;
const middleware = izara.middlewareHandler;&lt;br /&gt;
const recordHandlerSharedLib = require(&amp;quot;@izara_project/izara-shared&amp;quot;).recordHandlerSharedLib&lt;br /&gt;
const Logger = require(&amp;#039;@izara_project/izara-core-library-logger&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
const processProduct = require(&amp;#039;./ProcessProduct&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
// validate event properties in body.Message of sqs event&lt;br /&gt;
middleware.setValidatorSchema(recordHandlerSharedLib.baseValidatorSchema());&lt;br /&gt;
// set schema for record.body.Message&lt;br /&gt;
const perRecordsValidatorSchema = {&lt;br /&gt;
  type: &amp;quot;object&amp;quot;,&lt;br /&gt;
  required: [&lt;br /&gt;
    &amp;#039;productId&amp;#039;&lt;br /&gt;
  ],&lt;br /&gt;
  properties: {&lt;br /&gt;
    productId: {&lt;br /&gt;
      type: &amp;#039;string&amp;#039;,&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
// // set schema for record.body.MessageAttributes&lt;br /&gt;
// const messageAttributeValidatorSchema = {&lt;br /&gt;
//   type: &amp;quot;object&amp;quot;,&lt;br /&gt;
//   required: [&amp;#039;msgAtrrParam1&amp;#039;, &amp;#039;msgAtrrParam2&amp;#039;],&lt;br /&gt;
//   properties: {&lt;br /&gt;
//     msgAtrrParam1: {&lt;br /&gt;
//       type: &amp;quot;string&amp;quot;&lt;br /&gt;
//     },&lt;br /&gt;
//     msgAtrrParam2: {&lt;br /&gt;
//       type: &amp;quot;object&amp;quot;&lt;br /&gt;
//     }&lt;br /&gt;
//   }&lt;br /&gt;
// };&lt;br /&gt;
&lt;br /&gt;
module.exports.main = middleware.wrap(async (event, context, callback) =&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
  try {&lt;br /&gt;
&lt;br /&gt;
    let recordPromises = [];&lt;br /&gt;
&lt;br /&gt;
    // loop each record and send to mainFunction&lt;br /&gt;
    await Promise.all(event.Records.map(async record =&amp;gt; { // promise.all for map() function&lt;br /&gt;
&lt;br /&gt;
      let passOnProperties = []&lt;br /&gt;
      record._izContext.logger.debug(&amp;#039;record ReceiveMsgOutHdrSqs&amp;#039;, record);&lt;br /&gt;
&lt;br /&gt;
      //validate message (and MessageAttributes)&lt;br /&gt;
      await recordHandlerSharedLib.validateRecord(&lt;br /&gt;
        record,                             // one record will send to mainFunction&lt;br /&gt;
        &amp;quot;ProcessProduct&amp;quot;,                   // queue name that need to retry or send to dlq&lt;br /&gt;
        perRecordsValidatorSchema,          // schema for record.Message&lt;br /&gt;
        // messageAttributeValidatorSchema   // ----- for msgAttr default is null -&amp;gt; do not send this parameter if not want to validate msgAtt&lt;br /&gt;
      );&lt;br /&gt;
&lt;br /&gt;
      // add argument (to invoke lambda) to passOnProperties[]&lt;br /&gt;
      passOnProperties.push(record.body.Message.productId)&lt;br /&gt;
      record._izContext.logger.debug(&amp;#039;passOnProperties in handler&amp;#039;, passOnProperties);&lt;br /&gt;
&lt;br /&gt;
      // call recordHandlerSharedLib.recordHandler with 3 parameters and return promise(resolve)&lt;br /&gt;
      let recordPromise = recordHandlerSharedLib.recordHandler(&lt;br /&gt;
        record,                         // one record will send to mainFunction&lt;br /&gt;
        processProduct.processProduct,  // mainFunction that need to invoke.&lt;br /&gt;
        &amp;quot;ProcessProduct&amp;quot;,               // queue name that need to retry or send to dlq&lt;br /&gt;
        passOnProperties,               // all parameters that mainFunction needed.&lt;br /&gt;
      );&lt;br /&gt;
      record._izContext.logger.debug(&amp;#039;after recordPromise in handler&amp;#039;);&lt;br /&gt;
      recordPromises.push(recordPromise); // push promise to recordPromises&lt;br /&gt;
    }))&lt;br /&gt;
&lt;br /&gt;
    Logger.debug(&amp;#039;before Promise.all(recordPromises) in handler&amp;#039;);&lt;br /&gt;
    try {&lt;br /&gt;
      // --- main await all promises&lt;br /&gt;
      await Promise.all(recordPromises); // await all promises&lt;br /&gt;
&lt;br /&gt;
      return event.Records // return all for local testing&lt;br /&gt;
&lt;br /&gt;
    } catch {&lt;br /&gt;
      Logger.debug(&amp;#039;Promise.all(recordPromises) in handler threw error (at least one record did no resolve&amp;#039;);&lt;br /&gt;
    }&lt;br /&gt;
    Logger.debug(&amp;#039;after Promise.all(recordPromises) in handler&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
  } catch (err) {&lt;br /&gt;
    Logger.error(&amp;#039;Unhandled Error, ProcessProduct_HdrSqs: &amp;#039;, err);&lt;br /&gt;
    throw (err);&lt;br /&gt;
  }&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* function.yml&lt;br /&gt;
For Sqs handler ex: ProcessProduct_HdrSqs&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
ProcessProductSqs:&lt;br /&gt;
  handler: src/ProcessProduct_HdrSqs.main&lt;br /&gt;
  name: ${self:custom.iz_resourcePrefix}ProcessProductHdrSqs&lt;br /&gt;
  events:&lt;br /&gt;
    - sqs:&lt;br /&gt;
        arn: arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}ProcessProduct&lt;br /&gt;
        batchSize: 10&lt;br /&gt;
        # filterPatterns: # **** need to update serveless framework upper v.2.69.1&lt;br /&gt;
        #   - body: {&amp;quot;MessageAttributes&amp;quot;: {&amp;quot;callingFlow&amp;quot;: {&amp;quot;Value&amp;quot;: [&amp;quot;${self:custom.iz_serviceName}ProcessProduct&amp;quot;]} } } # TestFilter is function name of callingflow&lt;br /&gt;
        #   - body: {&amp;quot;MessageAttributes&amp;quot;: {&amp;quot;callingFlow&amp;quot;: {&amp;quot;Value&amp;quot;: [{&amp;quot;exists&amp;quot;:false}]} } }&lt;br /&gt;
  iamRoleStatements:&lt;br /&gt;
    - Effect: Allow&lt;br /&gt;
      Action:&lt;br /&gt;
        - sqs:SendMessage&lt;br /&gt;
        - sqs:ReceiveMessage&lt;br /&gt;
        - sqs:DeleteMessage&lt;br /&gt;
        - sqs:GetQueueAttributes&lt;br /&gt;
        - SNS:Publish&lt;br /&gt;
        - dynamodb:PutItem&lt;br /&gt;
        - dynamodb:GetItem&lt;br /&gt;
        - dynamodb:Query&lt;br /&gt;
        - dynamodb:DeleteItem&lt;br /&gt;
        - dynamodb:UpdateItem&lt;br /&gt;
      Resource:&lt;br /&gt;
        - arn:aws:dynamodb:${self:custom.iz_region}:${self:custom.iz_accountId}:table/${self:custom.iz_resourcePrefix}Config&lt;br /&gt;
        - arn:aws:dynamodb:${self:custom.iz_region}:${self:custom.iz_accountId}:table/${self:custom.iz_resourcePrefix}ProductRecord&lt;br /&gt;
        - &amp;quot;arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}InProcessProduct&amp;quot; #sns msgIn or Out Topicname&lt;br /&gt;
        - &amp;quot;arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}ProcessProduct&amp;quot; # for reties&lt;br /&gt;
        - &amp;quot;arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}ProcessProductDLQ&amp;quot;&lt;br /&gt;
        - &amp;quot;arn:aws:sns:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}OutProductComplete&amp;quot; #sns msgIn or Out Topicname&lt;br /&gt;
        //* add more.....&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* core-function.yml&lt;br /&gt;
add role in resource of InitialSetup and InitialSetupTestEnv&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
resource:&lt;br /&gt;
    - ${self:custom.iz_prefixIamRole}ProcessProductSqs${self:custom.iz_suffixIamRole} # eg. PutRolePolicy&lt;br /&gt;
    //* add more....&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== in resource ==&lt;br /&gt;
* sns-out.yml&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
Resources:&lt;br /&gt;
# ------[Create topic out]&lt;br /&gt;
  OutProductComplete:&lt;br /&gt;
    Type: AWS::SNS::Topic&lt;br /&gt;
    Properties:&lt;br /&gt;
      DisplayName: &amp;quot;SNS Message out&amp;quot;&lt;br /&gt;
      TopicName: ${self:custom.iz_resourcePrefix}OutProductComplete&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* sns-in-sqs.yml&lt;br /&gt;
ex: ProcessProduct_HdrSqs&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;YAML&amp;quot;&amp;gt;&lt;br /&gt;
Resources:&lt;br /&gt;
# ProcessProduct_HdrSqs: sns -&amp;gt; sqs -&amp;gt; lambda&lt;br /&gt;
# -------[Create Topic In]&lt;br /&gt;
  InProcessProduct:&lt;br /&gt;
    Type: AWS::SNS::Topic&lt;br /&gt;
    Properties:&lt;br /&gt;
      DisplayName: &amp;quot;SNS Message in&amp;quot;&lt;br /&gt;
      TopicName: ${self:custom.iz_resourcePrefix}InProcessProduct&lt;br /&gt;
  # -------[Topic In]&lt;br /&gt;
  SubscriptionInProcessProduct:&lt;br /&gt;
    Type: AWS::SNS::Subscription&lt;br /&gt;
    Properties:&lt;br /&gt;
      TopicArn: !Ref InProcessProduct&lt;br /&gt;
      Endpoint: &amp;quot;arn:aws:sqs:${self:custom.iz_region}:${self:custom.iz_accountId}:${self:custom.iz_resourcePrefix}ProcessProduct&amp;quot;&lt;br /&gt;
      Protocol: &amp;quot;sqs&amp;quot;&lt;br /&gt;
#----[Queue]&lt;br /&gt;
  ProcessProduct:&lt;br /&gt;
    Type: &amp;quot;AWS::SQS::Queue&amp;quot;&lt;br /&gt;
    Properties:&lt;br /&gt;
      QueueName: ${self:custom.iz_resourcePrefix}ProcessProduct&lt;br /&gt;
      RedrivePolicy:&lt;br /&gt;
        deadLetterTargetArn:&lt;br /&gt;
        # !GetAtt&lt;br /&gt;
          Fn::GetAtt:&lt;br /&gt;
            - ProcessProductDLQ&lt;br /&gt;
            - Arn&lt;br /&gt;
        maxReceiveCount: 3&lt;br /&gt;
      VisibilityTimeout: 120&lt;br /&gt;
  #----[QueueDLQ]&lt;br /&gt;
  ProcessProductDLQ:&lt;br /&gt;
    Type: AWS::SQS::Queue&lt;br /&gt;
    Properties:&lt;br /&gt;
      QueueName: ${self:custom.iz_resourcePrefix}ProcessProductDLQ&lt;br /&gt;
  #----[DataPolicy]&lt;br /&gt;
  ProcessProductPolicy:&lt;br /&gt;
    Type: AWS::SQS::QueuePolicy&lt;br /&gt;
    Properties:&lt;br /&gt;
      PolicyDocument:&lt;br /&gt;
        Version: &amp;quot;2012-10-17&amp;quot;&lt;br /&gt;
        Statement:&lt;br /&gt;
          - Sid: &amp;quot;allow-sns-messages&amp;quot;&lt;br /&gt;
            Effect: Allow&lt;br /&gt;
            Principal: &amp;quot;*&amp;quot;&lt;br /&gt;
            Resource:&lt;br /&gt;
            # !GetAtt&lt;br /&gt;
              Fn::GetAtt:&lt;br /&gt;
                - ProcessProduct&lt;br /&gt;
                - Arn&lt;br /&gt;
            Action: &amp;quot;SQS:SendMessage&amp;quot;&lt;br /&gt;
      Queues:&lt;br /&gt;
        - Ref: ProcessProduct&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* serverless.yml &lt;br /&gt;
add sns-out.yml and sns-in-sqs.yml in resources&lt;/div&gt;</summary>
		<author><name>Praew</name></author>
	</entry>
</feed>