2

将来、特定の時刻にawsラムダ関数を呼び出す予定のcloudwatchイベントを作成しています。ここで説明したように、私が使用していますAWS nodejs SDK:http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.htmlAwsラムダ関数addPermissionエラー:PolicyLengthExceededException

CloudWatchのイベントを作成するためのコードブロックは次のようになります。機能上

module.exports.createReservationReminder = function (reservationModel, user, restaurant) { 
return new Promise(function (resolve, reject) { 
    const ruleName = "rsv_" + reservationModel.reservationId; 
    const description = "Reservation reminder of `" + user.name + "` @ `" + restaurant.title + "` on `" + reservationModel.time + "`"; 
    let reservationTime = reservationModel.time; 
    let lambdaFunctionName = module.exports.buildLamdaFunctionArn("restaurant") 

    let alertTime = moment(reservationTime).tz(AppConfig.defaultTimezone).subtract(// Create alert 45 minute before a reservation 
      45, 
      'minutes' 
     ); 

    let lambda = new AWS.Lambda({ 
     accessKeyId: AppConfig.accessKeyId, 
     secretAccessKey: AppConfig.secretAccessKey, 
     region: AppConfig.region 
    }); 

    let scheduleExpression1 = "cron(" + alertTime.utc().format('m H D MMM ? YYYY') + ')'; 

    let ruleParams = { 
     Name: ruleName, 
     Description: description, 
     ScheduleExpression: scheduleExpression1, 
     State: 'ENABLED', 
    }; 
    cloudwatchevents.deleteRule({Name: ruleName}, function (err, deleteRuleData) { //remove if a previous rule was created halfway 
     cloudwatchevents.putRule(ruleParams, function (err, ruleData) { //create the rule 
      if (err) { 
       reject(err) 
      } 
      else { 


       let lambdaPermission = { 
        FunctionName: lambdaFunctionName, 
        StatementId: ruleName, 
        Action: 'lambda:InvokeFunction', 
        Principal: 'events.amazonaws.com', 
        SourceArn: ruleData.RuleArn 
       }; 

       let removePermission = { 
        FunctionName: lambdaFunctionName, 
        StatementId: ruleName, 
       } 

       //now to create the rule's target, need to add permission to lambda 
       lambda.removePermission(removePermission, function (err, removeLambdaData) { //remove if rule of same name was added as permission to this lambda before, ignore if rule not found error is thrown 
        lambda.addPermission(lambdaPermission, function (err, lamdaData) { //now add the permission 
         if (err) { 
          reject(err) // FAIL : throws error PolicyLengthExceededException after ~50 cloudwatch events are registered to this lambda function 
         } 
         else { 
          let targetParams = { 
           Rule: ruleName, 
           Targets: [ 
            { 
             Arn: module.exports.buildLamdaFunctionArn("restaurant"), 
             Id: ruleName, 
             Input: JSON.stringify({ 
              func: "notifyUserOfUpcomingReservation", 
              data: { 
               reservationId: reservationModel.reservationId 
              } 
             }), 

            }, 

           ] 
          }; 
          cloudwatchevents.putTargets(targetParams, function (err, targetData) { 
           if (err) { 
            reject(err) 
           } 
           else { 
            resolve(targetData) 
           } 
          }) 
         } 
        }) 
       }) 
      } 
     }); 
    }) 


}) 

}

が最初のため正常に動作〜50倍(したがって、50個の予約を簡単に思い出すことができます)。しかし、最終的にはいつも失敗するでしょう:

PolicyLengthExceededException ラムダ関数のアクセスポリシーは20 KBに制限されています。

HTTPステータスコード:400

政策文書が大きすぎることができないとして、理にかなっています。 この問題にアプローチする正しい方法は何ですか:lambda関数のターゲットで無制限のクラウドウォークイベントリマインダーを作成します。

+2

あなたは発砲する必要があるイベントをそれぞれ作成していますか?私はそれが他の理由で拡大縮小するとは思わない。より良い戦略は、5分ごとに発生する1回の定期的なイベントで、テーブル(例:DynamoDBまたはRDS)を照会して、未送信の通知を「今すぐ」に送信する必要があるかどうかを確認し、2回目の呼び出しラムダ関数。思考? –

+0

私は持つことができるクラウドウォッチイベントの数の制限のために、ちょうどそれをやって終わった:( –

答えて

1

ロールを作成し、そのロールにそのポリシーまたはアクセス許可を追加すると、ラムダがロールを引き継ぎ実行することができます。 aws STSモジュールを使用できます。

毎回権限を作成して削除するのではなく、 STSは一時的に役割を担い、コードを実行します。

+0

これは確かに問題の正しいアプローチです。しかし、スケジュールされたイベントの最大数にも限界があります(100)。だから、@ michael-sqlbotが提案したことをやめた –