目录

介绍

解释代码

解析函数

特别案例

AWS设置

AWS Lambda

AWS API网关

AWS Amplify


  • 下载 index.html - 884 B​​​​​​​
  • 下载 index.js.txt - 3.1 KB

介绍

这个项目对我来说有点锻炼。我最近开始在AWS中学习初学者的东西,所以我想通过创建一个简单的API来测试Lambda函数。本文介绍了如何使用AWS Lambda(一个使用AWS Amplify的简单网站)创建API函数,并使用AWS API Gateway连接这两者。

lambda函数本身是一个用Node.js编写的cron表达式解析器。它将Cron表达式作为参数,并在该cron表达式下一次触发事件时计算并返回。

解释代码

通过API事件接收的表达式首先针对两个表达式进行测试,如果匹配,则将其拆分为要解析的数组。

var matches_POSIX = regex_POSIX.exec(testexp);
var matches_EXT = regex_EXT.exec(testexp);
var arr = [];
if(matches_POSIX === null && matches_EXT === null) {console.log("Expression does not match!!!");return null;
}
else if(matches_POSIX !== null) {console.log("Expression is POSIX");arr.push("*");matches_POSIX.forEach((m, i) => i != 0 ? arr.push(m) : null);arr.push("*");if(arr[3] != "?" && arr[5] == "*") arr[5] = "?";if(arr[5] != "?" && arr[3] == "*") arr[3] = "?";
}
else {console.log("Expression is EXTENDED");matches_EXT.forEach((m, i) => i != 0 ? arr.push(m) : null);
}

主要功能是getNextTime。它将遍历数组的所有元素并使用适当的参数调用resolve函数。它还将测试已解决的错误值,这基本上是返回数组的第一个元素中的值-1。

解析顺序为:年-月-星期-日-时-分-秒。这种倒推方法的原因是因为,例如,要知道一个月有多少天,我们需要知道它是哪一年,要知道某个日期的哪个工作日,我们需要知道月份和年份等。

稍后我们在确定下一个触发cron事件的时间时也会使用这种方法,因为我们希望通过获取最接近的未来日期来缩小时间窗口;这将在后面的文本中更彻底地解释。

解析函数

根据正在求值的cron表达式的哪一部分(通过第二个参数传递),这个函数被分成几个部分;参数值的含义在上面的注释中解释了:

switch(i) {// yearcase 6:if(m === "*") return Array.apply(null, Array(10)).map(function(e, i){ return ts.getFullYear() + i; }); // current and next 9 yearsif(!m.includes("-") && !m.includes(","))return [parseInt(m, 10)];         // single valuereturn resolveList(m, i);              // list of years// monthcase 4:if(m === "*") return Array.apply(null,Array(12)).map(function(e, i) { return i; }); // return all monthsif(!m.includes("-") && !m.includes(",") && !isNaN(parseInt(m, 10)))return [parseInt(m, 10)-1];                   // single value numericif(isNaN(parseInt(m, 10)) && month2num(m) != -1)return [month2num(m)-1];                      // single value stringreturn resolveList(m, i).map(function(e,i){ return (e > 0 ? e-1 : e) }); // list of months// day of monthcase 3:if(m === "?") return undefined; // empty - use dw insteadif(m === "*") return Array.apply(null, Array(new Date(yyyy, mm+1, 0).getDate())).map(function(e, i){ return i + 1; });         // return all daysif(m.replace(/L|W/g,"").length != m.length)return null;                // last (week)day of month - skip,// resolve outside this functionif(!m.includes("-") && !m.includes(","))return [parseInt(m, 10)];    // single valuereturn resolveList(m, i);       // list of days// day of weekcase 5:if(m.replace(/L|#/g,"").length != m.length)return null;                    // just ignore special cases,// to be resolved outside this functionif(m === "?") return undefined;    // empty - use dd insteadif(m === "*") return Array.apply(null, Array(7)).map(function(e, i) { return i; }); // return all daysif(!m.includes("-") && !m.includes(","))return [parseInt(m, 10)];       // single value numericif(isNaN(parseInt(m, 10)) && day2num(m) != -1)return [day2num(m)];            // single value stringreturn resolveList(m, i);          // list of days// hourcase 2:if(m === "*") return Array.apply(null,Array(24)).map(function(e, i) { return i; }); // return all hoursif(!m.includes("-") && !m.includes(",") && !m.includes("/"))return [parseInt(m, 10)];      // single valuereturn resolveList(m, i);          // list of hours// min / seccase 1: case 0:if(m === "*") return Array.apply(null, Array(60)).map(function(e, i){ return i; });                // return all min/secif(!m.includes("-") && !m.includes(",") && !m.includes("/"))return [parseInt(m, 10 )];     // single valuereturn resolveList(m, i);          // list of min/sec
}

该resolve函数尝试为cron的每个部分返回一个包含所有可能值的数组(年份除外;因为年份是无限的,该函数最多将返回未来10年)。

如果提供了星号(*),则表示所有的值都是可能的,因此首先使用Array.apply函数创建一个数组,以null元素为初始值,然后使用map函数设置元素,例如12个月:

if(m === "*") return Array.apply(null, Array(12)).map(function(e, i) { return i; }); // return all months

可能的结果要么是所有值(*),只有一个值,要么是用逗号分隔的列表或范围表示的值列表——这在名为resolveList的单独函数中解析:

function resolveList(m, i) {var retValue = [];var msplit;var k;var limit;if(m.includes("-")) { // all in betweenmsplit = m.split("-").map(function(e) {if(i == 4) e = month2num(e);if(i == 5) e = day2num(e);return parseInt(e, 10);});if (msplit[0] < msplit[1]) {for(k = msplit[0]; k <= msplit[1]; k++) retValue.push(k);}else {console.log("error: illegal expression " + m);retValue.push(-1);}return retValue;}else if(m.includes(",")) {         // all listedm.split(",").map(function(e) { // convert to intreturn parseInt(e, 10);}).forEach(k => {              // remove duplicates//console.log("currentValue=" + k + " ; retValue=" + retValue.toString());if(!retValue.includes(k)) retValue.push(k);});return retValue.sort();        // sort//m.split(",").forEach(k => retValue.push(parseInt(k)));}else if(m.includes("/")) {msplit = m.split("/");if(msplit[0] == "*") msplit[0] = "0";msplit = msplit.map(function(e) {return parseInt(e, 10);});if(i <= 1) limit = 60;         // seconds/minutesif(i == 2) limit = 12;         // seconds/minutesfor(k = msplit[0] + msplit[1]; k <= limit; k = k + msplit[1]) retValue.push(k == limit ? 0 : k);}return retValue;}

特别案例

所有特殊值,例如L、W或_#_都在resolve函数之外解析,因为它们只有在我们已经缩小时间范围后才能解析。它们在函数specialDay和specialDate中解析,直接从主函数调用:

function specialDate(exp, mm, yyyy) {if(exp == "L")return new Date(yyyy, mm + 1, 0).getDate();if(exp == "LW")for(var i = new Date(yyyy, mm + 1, 0).getDate(); i > 0; i--) {if([1, 2, 3, 4, 5].includes(new Date(yyyy, mm, i).getDay()))return i;}if(exp.substring(0, 1) == "L-")if(!isNaN(parseInt(exp.substring(2), 10)))return new Date(yyyy, mm + 1, 0).getDate()+1 - parseInt(exp.substring(2), 10);}function specialDay(exp, mm, yyyy) {if(exp.includes("L"))for(var i = new Date(yyyy, mm + 1, 0).getDate(); i > 0; i--) { // start from end of month and look for last specified weekday in that monthif(parseInt(exp.substring(0,1),10) == new Date(yyyy, mm, i).getDay())return i;}if(exp.includes("#")) {var n = 0;for(i = 1; i <= new Date(yyyy, mm + 1, 0).getDate(); i++) { // start from beginning of the month and count (n) // the occurences of specified weekday in that monthif(parseInt(exp.substring(0,1),10) == new Date(yyyy, mm, i).getDay()) {n++;if(n == parseInt(exp.substring(2,3),10)) return i;i = i+6;}}}return undefined;}

AWS设置

AWS Lambda

转到AWS Lambda并单击“创建函数”。

选择“Author from scratch”,输入函数名,即“cron-parse”,在“Runtime”下选择“Node.js”,点击“Create function”。

您将看到一个带有“Function overview”和“Code Source”部分的屏幕:

将您的代码粘贴到“index.js”下,然后单击“部署”。

在“测试”下拉菜单(箭头菜单)下,点击“配置测试事件”。有了这个,您可以指定一个测试表达式(JSON)并查看结果输出。你可以输入例如:

{"key1": "5/15 12-15 3-5 ? 7,5,3 WED-FRI 2021-2022"
}

为您的活动命名,比方说test1,然后按“创建”按钮。

然后,当您单击“测试”按钮时,您应该得到以下输出:

AWS API网关

转到AWS API Gateway并单击“创建 API”。

点击“Rest API”下的“Build”。

选择“REST – API”。输入名称,例如cronAPI。

在“端点类型”下,选择“边缘优化”。

点击“创建API ”。

在“资源”下,转到“操作”菜单并选择“创建方法”。

在创建的方法中,选择“POST”并点击确认标记。

选择“Lambda函数”作为“集成类型”(确保您使用的区域与创建Lambda函数的区域相同),输入您的Lambda函数的名称 (cron-parse) 并单击“保存”,然后单击“确定”。

再次转到“操作”菜单,选择“启用CORS”,然后单击“启用CORS并替换现有...

从“Actions”菜单中,选择“Deploy API”,“Deployment stage”=“New stage”,输入stag名称(例如dev,然后点击“Deploy”。

从页面顶部复制“调用URL ”——稍后您将需要它。

AWS Amplify

转到AWS Amplify,一直往下走,然后单击“Develop”块中的“Get Started” 。

输入应用名称,例如“Cron parser”。确认部署并放松并享受AWS在后台为您做的一切。

转到“前端环境”选项卡,选择“不使用 Git提供程序部署”,然后单击“连接分支”。

在您的计算机上(本地),使用以下代码创建一个名为“index.html”的简单HTML文件:

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>Cron parser</title><script>// define the callAPI function that takes a first name and last name as parametersvar callAPI = (key1)=>{// instantiate a headers objectvar myHeaders = new Headers();// add content type header to objectmyHeaders.append("Content-Type", "application/json");// using built in JSON utility package turn object // to string and store in a variablevar raw = JSON.stringify({"key1":key1});// create a JSON object with parameters for API call and store in a variablevar requestOptions = {method: 'POST',headers: myHeaders,body: raw,redirect: 'follow'};// make API call with parameters and use promises to get responsefetch("YOUR API INVOKE URL HERE", requestOptions).then(response => response.text()).then(result => document.getElementById('result').innerHTML = result/*alert(JSON.parse(result).body)*/).catch(error => document.getElementById('result').innerHTML = error/*console.log('error', error)*/);}</script>
</head><body><label for="incron">Enter Cron expression here </label><input type="text" name="incron" id="incron"><button type="button" onclick="callAPI(document.getElementById('incron').value)">Submit</button><br/><hr/><br/><label for="result">Result: </label><div name="result" id="result"></div>
</body>
</html>

将“YOUR API INVOKE URL HERE”替换为您在上一步中保存的URL。

保存“index.html”,然后ZIP(压缩)它(您可以随意命名ZIP)。

现在返回AWS控制台(您的Amplify应用程序),然后单击“选择文件”,然后打开包含“index.html”的zip 。保存并部署。

就是这样。现在您可以使用“Domain”下的URL打开您的HTML网页。输入一个cron表达式来测试它并单击Submit,您的API应该在Result下返回一个值。

AWS Lambda中的Cron表达式解析器相关推荐

  1. 如何使用Node.js和CloudFormation在AWS Lambda中构建和部署GraphQL服务器

    介绍 (Introduction) I have been building GraphQL APIs in a Serverless environment for over 3 years now ...

  2. cron表达式解析 + robfig/cron 源码剖析

    robfiig/cron 源码剖析 Cron 表达式 参考wiki https://en.wikipedia.org/wiki/Cron robfiig/cron项目信息 下载地址 https://g ...

  3. 表达式解析器(MVEL)

    Jeval 在运行时解析计算静态和动态表达式:支持数学,布尔,字符串,函数表达式:支持大部分的数学和布尔运算符:支持自定义函数:支持嵌套函数:支持解析:支持自定义变量解析器: 官网:http://je ...

  4. 数学表达式解析器简介

    2019独角兽企业重金招聘Python工程师标准>>> 在实际项目开发中如果需要解析数学公式,无须再运用解释器模式进行设计,可以直接使用一些第三方解析工具包,它们可以统称为数学表达式 ...

  5. aws lambda使用_使用python了解AWS Lambda中的多处理

    aws lambda使用 Adding some transparency to the black box 为黑匣子添加一些透明度 Let me start with an observation. ...

  6. Postgresql源码(85)查询执行——表达式解析器分析(select 1+1如何执行)

    相关 <Postgresql源码(61)查询执行--最外层Portal模块> <Postgresql源码(62)查询执行--子模块ProcessUtility> <Pos ...

  7. aws lambda_它会融合吗? 或如何在AWS Lambda中运行Google Chrome

    aws lambda Yes, you read that right: this article is about running Google Chrome (the browser) in AW ...

  8. cron表达式解析 获取N条结果集

    这是我的cron表达式解析工具类: public class CronDateUtil {public static List<String> parser(String cronExpr ...

  9. 表达式解析器Mvel2.0(MVFLEX Expression Language)

    时间过的好快,突然就发现,已经过去一两年了,这一两年博客也写的不多,快要进入中年了,最重要的就是自律.要好好睡觉,好好学习,好好工作. 废话不多说,这次给大家说的是 表达式语言解析Mvel2.0 简介 ...

最新文章

  1. Docker如何将本地镜像发布到阿里云上去
  2. 无副作用、效果超越吗啡!用微电极精准管理大脑“疼痛中心”,科学家探索止痛新方法...
  3. 电单车拉力赛的调试情况汇集
  4. jQuery复选框选中状态更改事件
  5. 路径规划算法之Bellman-Ford算法
  6. python函数调用位置_Python: 浅谈函数局部变量快在哪
  7. [Win 7]Windows7 RC 简体中文版测试正式开始了哦!!
  8. python气象数据处理与绘图_Python气象数据处理与绘图:纬高图的另一种思路
  9. MooseFS源代码分析(三)
  10. 第九届中国开源黑客松活动将于2019年4月18日-4月20日,在深圳举办
  11. python实现车牌识别
  12. PHP亿乐社区源码一比一高仿全开源源码
  13. Rasa课程、Rasa培训、Rasa面试系列之:Rasa 3.x rasa run actions等运行命令学习
  14. 分类评价指标(二分类)——f1score sensitivity specificity roc曲线 auc
  15. 模拟量转数字量的本质
  16. 今日头条推荐算法详解(PDF下载)
  17. Unity游戏帧同步技术分享篇【01】帧同步解决方案概述
  18. ios 模拟器沙盒_查看iOS模拟器应用的沙箱文件
  19. Linux --------- 远程操作工具
  20. hangfire-简单开始

热门文章

  1. 在电脑上怎么打印文件_电脑上怎么mov格式怎么转换成mp4
  2. microsoft fix it_it狂人【14季全】
  3. linnux 流量控制模块tc_FS4008-40-08-CV-A气体质量流量计【汉川仪器】阿坝资讯
  4. php改变图片类型,php 图片处理函数 获取类型 扩展名
  5. idea在java文件中查找_Java开发工具IntelliJ IDEA使用源代码系列教程(四):在文件中搜索目标...
  6. mysql gps海拔表_GPS海拔表
  7. checkbox 多选 mysql 搜索_mySQL技术的方方面面,不管是应用还是面试,看这一文就够了...
  8. syslog工具_07 Docker 可视化管理和监控工具
  9. 风格和个性!一组微质感图标设计灵感
  10. Android设计原则及规范指南!UI设计师值得一看!