@stacksjs/cloud 0.58.56 → 0.58.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +145 -54
- package/package.json +28 -28
- package/src/cloud/aws-sdk-layer/nodejs/package-lock.json +6 -6
- package/src/cloud/aws-sdk-layer/nodejs/package.json +2 -2
- package/src/cloud/index.ts +76 -50
- package/src/cloud/queue.ts +106 -9
- package/src/cloud/router-layer/nodejs/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1795,21 +1795,73 @@ class ComputeStack {
|
|
|
1795
1795
|
|
|
1796
1796
|
// src/cloud/queue.ts
|
|
1797
1797
|
import {aws_ec2 as ec24} from "aws-cdk-lib";
|
|
1798
|
+
import {pascalCase, slug as slug2} from "@stacksjs/strings";
|
|
1799
|
+
import {fs} from "@stacksjs/storage";
|
|
1800
|
+
import {path as path6} from "@stacksjs/path";
|
|
1798
1801
|
import {Rule, Schedule} from "aws-cdk-lib/aws-events";
|
|
1799
1802
|
import {EcsTask} from "aws-cdk-lib/aws-events-targets";
|
|
1800
1803
|
|
|
1801
1804
|
class QueueStack {
|
|
1805
|
+
scope;
|
|
1806
|
+
props;
|
|
1802
1807
|
constructor(scope, props) {
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1808
|
+
this.scope = scope;
|
|
1809
|
+
this.props = props;
|
|
1810
|
+
}
|
|
1811
|
+
async init() {
|
|
1812
|
+
const jobsDir = path6.jobsPath();
|
|
1813
|
+
try {
|
|
1814
|
+
const jobFiles = await fs.readdir(jobsDir);
|
|
1815
|
+
const actionFiles = await fs.readdir(actionsDir);
|
|
1816
|
+
const jobs = [];
|
|
1817
|
+
for (const file2 of jobFiles) {
|
|
1818
|
+
if (!file2.endsWith(".ts"))
|
|
1819
|
+
continue;
|
|
1820
|
+
const filePath = path6.jobsPath(file2);
|
|
1821
|
+
jobs.push(await this.loadModule(filePath));
|
|
1822
|
+
}
|
|
1823
|
+
for (const file2 of actionFiles) {
|
|
1824
|
+
if (!file2.endsWith(".ts"))
|
|
1825
|
+
continue;
|
|
1826
|
+
const filePath = path6.actionsPath(file2);
|
|
1827
|
+
jobs.push(await this.loadModule(filePath));
|
|
1828
|
+
}
|
|
1829
|
+
for (const job of jobs)
|
|
1830
|
+
await this.createQueueRule(job);
|
|
1831
|
+
} catch (err2) {
|
|
1832
|
+
console.error("Error reading the jobs directory:", err2);
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
cronScheduleFromRate(rate) {
|
|
1836
|
+
const parts = rate.split(" ");
|
|
1837
|
+
return {
|
|
1838
|
+
minute: parts[0],
|
|
1839
|
+
hour: parts[1],
|
|
1840
|
+
month: parts[2],
|
|
1841
|
+
weekDay: parts[3],
|
|
1842
|
+
year: parts[4]
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1845
|
+
async loadModule(filePath) {
|
|
1846
|
+
const jobModule2 = await import(filePath);
|
|
1847
|
+
return jobModule2;
|
|
1848
|
+
}
|
|
1849
|
+
createQueueRule(job) {
|
|
1850
|
+
const rate = job.default?.rate;
|
|
1851
|
+
if (!rate || job.default?.enabled === false)
|
|
1852
|
+
return;
|
|
1853
|
+
const schedule = Schedule.cron(this.cronScheduleFromRate(rate));
|
|
1854
|
+
const id = `QueueRule${pascalCase(file.replace(".ts", ""))}`;
|
|
1855
|
+
const rule = new Rule(this.scope, id, {
|
|
1856
|
+
ruleName: `${this.props.appName}-${this.props.appEnv}-queue-rule-${slug2(file.replace(".ts", ""))}`,
|
|
1857
|
+
schedule
|
|
1806
1858
|
});
|
|
1807
1859
|
rule.addTarget(new EcsTask({
|
|
1808
|
-
cluster: props.cluster,
|
|
1809
|
-
taskDefinition: props.taskDefinition,
|
|
1860
|
+
cluster: this.props.cluster,
|
|
1861
|
+
taskDefinition: this.props.taskDefinition,
|
|
1810
1862
|
containerOverrides: [
|
|
1811
1863
|
{
|
|
1812
|
-
containerName: `${props.appName}-${props.appEnv}-api`,
|
|
1864
|
+
containerName: `${this.props.appName}-${this.props.appEnv}-api`,
|
|
1813
1865
|
environment: [
|
|
1814
1866
|
{
|
|
1815
1867
|
name: "QUEUE_WORKER",
|
|
@@ -1817,12 +1869,28 @@ class QueueStack {
|
|
|
1817
1869
|
},
|
|
1818
1870
|
{
|
|
1819
1871
|
name: "JOB",
|
|
1820
|
-
value:
|
|
1872
|
+
value: file
|
|
1873
|
+
},
|
|
1874
|
+
{
|
|
1875
|
+
name: "JOB_BACKOFF_FACTOR",
|
|
1876
|
+
value: jobModule.default?.backoffFactor
|
|
1877
|
+
},
|
|
1878
|
+
{
|
|
1879
|
+
name: "JOB_RETRIES",
|
|
1880
|
+
value: jobModule.default?.tries
|
|
1881
|
+
},
|
|
1882
|
+
{
|
|
1883
|
+
name: "JOB_INITIAL_DELAY",
|
|
1884
|
+
value: jobModule.default?.initialDelay
|
|
1885
|
+
},
|
|
1886
|
+
{
|
|
1887
|
+
name: "JOB_JITTER",
|
|
1888
|
+
value: jobModule.default?.jitter
|
|
1821
1889
|
}
|
|
1822
1890
|
]
|
|
1823
1891
|
}
|
|
1824
1892
|
],
|
|
1825
|
-
retryAttempts:
|
|
1893
|
+
retryAttempts: 1,
|
|
1826
1894
|
subnetSelection: {
|
|
1827
1895
|
subnetType: ec24.SubnetType.PUBLIC
|
|
1828
1896
|
}
|
|
@@ -1832,70 +1900,93 @@ class QueueStack {
|
|
|
1832
1900
|
|
|
1833
1901
|
// src/cloud/index.ts
|
|
1834
1902
|
class Cloud extends Stack2 {
|
|
1903
|
+
dns;
|
|
1904
|
+
security;
|
|
1905
|
+
storage;
|
|
1906
|
+
network;
|
|
1907
|
+
fileSystem;
|
|
1908
|
+
jumpBox;
|
|
1909
|
+
docs;
|
|
1910
|
+
email;
|
|
1911
|
+
redirects;
|
|
1912
|
+
permissions;
|
|
1913
|
+
ai;
|
|
1914
|
+
cli;
|
|
1915
|
+
api;
|
|
1916
|
+
cdn;
|
|
1917
|
+
queue;
|
|
1918
|
+
deployment;
|
|
1919
|
+
scope;
|
|
1920
|
+
props;
|
|
1835
1921
|
constructor(scope, id, props) {
|
|
1836
1922
|
super(scope, id, props);
|
|
1837
|
-
|
|
1838
|
-
|
|
1923
|
+
this.scope = scope;
|
|
1924
|
+
this.props = props;
|
|
1925
|
+
this.dns = new DnsStack(this, props);
|
|
1926
|
+
this.security = new SecurityStack(this, {
|
|
1839
1927
|
...props,
|
|
1840
|
-
zone:
|
|
1928
|
+
zone: this.dns.zone
|
|
1841
1929
|
});
|
|
1842
|
-
|
|
1930
|
+
this.storage = new StorageStack(this, {
|
|
1843
1931
|
...props,
|
|
1844
|
-
kmsKey:
|
|
1932
|
+
kmsKey: this.security.kmsKey
|
|
1845
1933
|
});
|
|
1846
|
-
|
|
1847
|
-
|
|
1934
|
+
this.network = new NetworkStack(this, props);
|
|
1935
|
+
this.fileSystem = new FileSystemStack(this, {
|
|
1848
1936
|
...props,
|
|
1849
|
-
vpc:
|
|
1937
|
+
vpc: this.network.vpc
|
|
1850
1938
|
});
|
|
1851
|
-
new JumpBoxStack(this, {
|
|
1939
|
+
this.jumpBox = new JumpBoxStack(this, {
|
|
1852
1940
|
...props,
|
|
1853
|
-
vpc:
|
|
1854
|
-
fileSystem: fileSystem.fileSystem
|
|
1941
|
+
vpc: this.network.vpc,
|
|
1942
|
+
fileSystem: this.fileSystem.fileSystem
|
|
1855
1943
|
});
|
|
1856
|
-
|
|
1857
|
-
new EmailStack(this, {
|
|
1944
|
+
this.docs = new DocsStack(this, props);
|
|
1945
|
+
this.email = new EmailStack(this, {
|
|
1858
1946
|
...props,
|
|
1859
|
-
zone:
|
|
1947
|
+
zone: this.dns.zone
|
|
1860
1948
|
});
|
|
1861
|
-
new RedirectsStack(this, props);
|
|
1862
|
-
new PermissionsStack(this);
|
|
1863
|
-
|
|
1949
|
+
this.redirects = new RedirectsStack(this, props);
|
|
1950
|
+
this.permissions = new PermissionsStack(this);
|
|
1951
|
+
this.ai = new AiStack(this, props);
|
|
1952
|
+
this.cli = new CliStack(this, props);
|
|
1953
|
+
}
|
|
1954
|
+
async init() {
|
|
1864
1955
|
if (config20.cloud.api?.deploy) {
|
|
1865
|
-
|
|
1956
|
+
const props = this.props;
|
|
1957
|
+
this.api = new ComputeStack(this, {
|
|
1866
1958
|
...props,
|
|
1867
|
-
vpc:
|
|
1868
|
-
fileSystem: fileSystem.fileSystem,
|
|
1869
|
-
zone:
|
|
1870
|
-
certificate:
|
|
1959
|
+
vpc: this.network.vpc,
|
|
1960
|
+
fileSystem: this.fileSystem.fileSystem,
|
|
1961
|
+
zone: this.dns.zone,
|
|
1962
|
+
certificate: this.security.certificate
|
|
1871
1963
|
});
|
|
1872
|
-
new QueueStack(this, {
|
|
1964
|
+
this.queue = new QueueStack(this, {
|
|
1873
1965
|
...props,
|
|
1874
|
-
cluster: api.cluster,
|
|
1875
|
-
taskDefinition: api.taskDefinition
|
|
1966
|
+
cluster: this.api.cluster,
|
|
1967
|
+
taskDefinition: this.api.taskDefinition
|
|
1968
|
+
});
|
|
1969
|
+
await this.queue.init();
|
|
1970
|
+
this.cdn = new CdnStack(this, {
|
|
1971
|
+
...props,
|
|
1972
|
+
publicBucket: this.storage.publicBucket,
|
|
1973
|
+
logBucket: this.storage.logBucket,
|
|
1974
|
+
certificate: this.security.certificate,
|
|
1975
|
+
firewall: this.security.firewall,
|
|
1976
|
+
originRequestFunction: this.docs.originRequestFunction,
|
|
1977
|
+
zone: this.dns.zone,
|
|
1978
|
+
cliSetupUrl: this.cli.cliSetupUrl,
|
|
1979
|
+
askAiUrl: this.ai.askAiUrl,
|
|
1980
|
+
summarizeAiUrl: this.ai.summarizeAiUrl,
|
|
1981
|
+
lb: this.api?.lb
|
|
1982
|
+
});
|
|
1983
|
+
this.deployment = new DeploymentStack(this, {
|
|
1984
|
+
...props,
|
|
1985
|
+
publicBucket: this.storage.publicBucket,
|
|
1986
|
+
privateBucket: this.storage.privateBucket,
|
|
1987
|
+
cdn: this.cdn.distribution
|
|
1876
1988
|
});
|
|
1877
1989
|
}
|
|
1878
|
-
const ai2 = new AiStack(this, props);
|
|
1879
|
-
const cli2 = new CliStack(this, props);
|
|
1880
|
-
const cdn2 = new CdnStack(this, {
|
|
1881
|
-
...props,
|
|
1882
|
-
publicBucket: storage5.publicBucket,
|
|
1883
|
-
logBucket: storage5.logBucket,
|
|
1884
|
-
certificate: security2.certificate,
|
|
1885
|
-
firewall: security2.firewall,
|
|
1886
|
-
originRequestFunction: docs2.originRequestFunction,
|
|
1887
|
-
zone: dns2.zone,
|
|
1888
|
-
cliSetupUrl: cli2.cliSetupUrl,
|
|
1889
|
-
askAiUrl: ai2.askAiUrl,
|
|
1890
|
-
summarizeAiUrl: ai2.summarizeAiUrl,
|
|
1891
|
-
lb: api?.lb
|
|
1892
|
-
});
|
|
1893
|
-
new DeploymentStack(this, {
|
|
1894
|
-
...props,
|
|
1895
|
-
publicBucket: storage5.publicBucket,
|
|
1896
|
-
privateBucket: storage5.privateBucket,
|
|
1897
|
-
cdn: cdn2.distribution
|
|
1898
|
-
});
|
|
1899
1990
|
}
|
|
1900
1991
|
}
|
|
1901
1992
|
export {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.58.
|
|
4
|
+
"version": "0.58.58",
|
|
5
5
|
"description": "The Stacks cloud/serverless integration & implementation.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"license": "MIT",
|
|
@@ -55,19 +55,19 @@
|
|
|
55
55
|
"prepublishOnly": "bun run build"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@aws-sdk/client-bedrock": "^3.
|
|
59
|
-
"@aws-sdk/client-cloudformation": "^3.
|
|
60
|
-
"@aws-sdk/client-cloudfront": "^3.
|
|
61
|
-
"@aws-sdk/client-cloudwatch-logs": "^3.
|
|
62
|
-
"@aws-sdk/client-ec2": "^3.
|
|
63
|
-
"@aws-sdk/client-efs": "^3.
|
|
64
|
-
"@aws-sdk/client-iam": "^3.
|
|
65
|
-
"@aws-sdk/client-lambda": "^3.
|
|
66
|
-
"@aws-sdk/client-route-53-domains": "^3.
|
|
67
|
-
"@aws-sdk/client-s3": "^3.
|
|
68
|
-
"@aws-sdk/client-ses": "^3.
|
|
69
|
-
"@aws-sdk/client-sesv2": "^3.
|
|
70
|
-
"@aws-sdk/client-ssm": "^3.
|
|
58
|
+
"@aws-sdk/client-bedrock": "^3.509.0",
|
|
59
|
+
"@aws-sdk/client-cloudformation": "^3.509.0",
|
|
60
|
+
"@aws-sdk/client-cloudfront": "^3.509.0",
|
|
61
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.509.0",
|
|
62
|
+
"@aws-sdk/client-ec2": "^3.509.0",
|
|
63
|
+
"@aws-sdk/client-efs": "^3.509.0",
|
|
64
|
+
"@aws-sdk/client-iam": "^3.509.0",
|
|
65
|
+
"@aws-sdk/client-lambda": "^3.509.0",
|
|
66
|
+
"@aws-sdk/client-route-53-domains": "^3.509.0",
|
|
67
|
+
"@aws-sdk/client-s3": "^3.509.0",
|
|
68
|
+
"@aws-sdk/client-ses": "^3.509.0",
|
|
69
|
+
"@aws-sdk/client-sesv2": "^3.509.0",
|
|
70
|
+
"@aws-sdk/client-ssm": "^3.509.0",
|
|
71
71
|
"@stacksjs/config": "latest",
|
|
72
72
|
"@stacksjs/env": "latest",
|
|
73
73
|
"@stacksjs/logging": "latest",
|
|
@@ -79,20 +79,20 @@
|
|
|
79
79
|
"@stacksjs/validation": "latest"
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@aws-sdk/client-bedrock": "^3.
|
|
83
|
-
"@aws-sdk/client-cloudformation": "^3.
|
|
84
|
-
"@aws-sdk/client-cloudfront": "^3.
|
|
85
|
-
"@aws-sdk/client-cloudwatch-logs": "^3.
|
|
86
|
-
"@aws-sdk/client-dynamodb": "3.
|
|
87
|
-
"@aws-sdk/client-ec2": "^3.
|
|
88
|
-
"@aws-sdk/client-efs": "^3.
|
|
89
|
-
"@aws-sdk/client-iam": "^3.
|
|
90
|
-
"@aws-sdk/client-lambda": "^3.
|
|
91
|
-
"@aws-sdk/client-route-53-domains": "^3.
|
|
92
|
-
"@aws-sdk/client-s3": "^3.
|
|
93
|
-
"@aws-sdk/client-ses": "^3.
|
|
94
|
-
"@aws-sdk/client-sesv2": "^3.
|
|
95
|
-
"@aws-sdk/client-ssm": "^3.
|
|
82
|
+
"@aws-sdk/client-bedrock": "^3.509.0",
|
|
83
|
+
"@aws-sdk/client-cloudformation": "^3.509.0",
|
|
84
|
+
"@aws-sdk/client-cloudfront": "^3.509.0",
|
|
85
|
+
"@aws-sdk/client-cloudwatch-logs": "^3.509.0",
|
|
86
|
+
"@aws-sdk/client-dynamodb": "3.509.0",
|
|
87
|
+
"@aws-sdk/client-ec2": "^3.509.0",
|
|
88
|
+
"@aws-sdk/client-efs": "^3.509.0",
|
|
89
|
+
"@aws-sdk/client-iam": "^3.509.0",
|
|
90
|
+
"@aws-sdk/client-lambda": "^3.509.0",
|
|
91
|
+
"@aws-sdk/client-route-53-domains": "^3.509.0",
|
|
92
|
+
"@aws-sdk/client-s3": "^3.509.0",
|
|
93
|
+
"@aws-sdk/client-ses": "^3.509.0",
|
|
94
|
+
"@aws-sdk/client-sesv2": "^3.509.0",
|
|
95
|
+
"@aws-sdk/client-ssm": "^3.509.0",
|
|
96
96
|
"@stacksjs/config": "latest",
|
|
97
97
|
"@stacksjs/dns": "latest",
|
|
98
98
|
"@stacksjs/env": "latest",
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aws-sdk-layer",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.57",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "aws-sdk-layer",
|
|
9
|
-
"version": "0.58.
|
|
9
|
+
"version": "0.58.57",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"aws-sdk": "^2.
|
|
12
|
+
"aws-sdk": "^2.1553.0"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"node_modules/available-typed-arrays": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
}
|
|
25
25
|
},
|
|
26
26
|
"node_modules/aws-sdk": {
|
|
27
|
-
"version": "2.
|
|
28
|
-
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.
|
|
29
|
-
"integrity": "sha512-
|
|
27
|
+
"version": "2.1553.0",
|
|
28
|
+
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1553.0.tgz",
|
|
29
|
+
"integrity": "sha512-CfZaw8dR9e642aBOeFhkFL7KoQApeLR15uH2IQqfL/12snWYayAAesYh0tEaU+XbhrH0CUsf2Zro5IraEXEZMg==",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"buffer": "4.9.2",
|
|
32
32
|
"events": "1.1.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aws-sdk-layer",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.58",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "ISC",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"aws-sdk": "^2.
|
|
13
|
+
"aws-sdk": "^2.1553.0"
|
|
14
14
|
}
|
|
15
15
|
}
|
package/src/cloud/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-new */
|
|
2
1
|
import { Stack } from 'aws-cdk-lib'
|
|
3
2
|
import type { Construct } from 'constructs'
|
|
4
3
|
import { config } from '@stacksjs/config'
|
|
@@ -23,87 +22,114 @@ import { QueueStack } from './queue'
|
|
|
23
22
|
// import { DashboardStack } from './dashboard'
|
|
24
23
|
|
|
25
24
|
export class Cloud extends Stack {
|
|
25
|
+
dns: DnsStack
|
|
26
|
+
security: SecurityStack
|
|
27
|
+
storage: StorageStack
|
|
28
|
+
network: NetworkStack
|
|
29
|
+
fileSystem: FileSystemStack
|
|
30
|
+
jumpBox: JumpBoxStack
|
|
31
|
+
docs: DocsStack
|
|
32
|
+
email: EmailStack
|
|
33
|
+
redirects: RedirectsStack
|
|
34
|
+
permissions: PermissionsStack
|
|
35
|
+
ai: AiStack
|
|
36
|
+
cli: CliStack
|
|
37
|
+
api!: ComputeStack
|
|
38
|
+
cdn!: CdnStack
|
|
39
|
+
queue!: QueueStack
|
|
40
|
+
deployment!: DeploymentStack
|
|
41
|
+
scope: Construct
|
|
42
|
+
props: CloudOptions
|
|
43
|
+
|
|
26
44
|
constructor(scope: Construct, id: string, props: CloudOptions) {
|
|
27
45
|
super(scope, id, props)
|
|
28
|
-
|
|
29
|
-
|
|
46
|
+
this.scope = scope
|
|
47
|
+
this.props = props
|
|
30
48
|
|
|
31
|
-
|
|
49
|
+
// please beware: be careful changing the order of the stack creations below
|
|
50
|
+
this.dns = new DnsStack(this, props)
|
|
51
|
+
this.security = new SecurityStack(this, {
|
|
32
52
|
...props,
|
|
33
|
-
zone: dns.zone,
|
|
53
|
+
zone: this.dns.zone,
|
|
34
54
|
})
|
|
35
55
|
|
|
36
|
-
|
|
56
|
+
this.storage = new StorageStack(this, {
|
|
37
57
|
...props,
|
|
38
|
-
kmsKey: security.kmsKey,
|
|
58
|
+
kmsKey: this.security.kmsKey,
|
|
39
59
|
})
|
|
40
60
|
|
|
41
|
-
|
|
61
|
+
this.network = new NetworkStack(this, props)
|
|
42
62
|
|
|
43
|
-
|
|
63
|
+
this.fileSystem = new FileSystemStack(this, {
|
|
44
64
|
...props,
|
|
45
|
-
vpc: network.vpc,
|
|
65
|
+
vpc: this.network.vpc,
|
|
46
66
|
})
|
|
47
67
|
|
|
48
|
-
new JumpBoxStack(this, {
|
|
68
|
+
this.jumpBox = new JumpBoxStack(this, {
|
|
49
69
|
...props,
|
|
50
|
-
vpc: network.vpc,
|
|
51
|
-
fileSystem: fileSystem.fileSystem,
|
|
70
|
+
vpc: this.network.vpc,
|
|
71
|
+
fileSystem: this.fileSystem.fileSystem,
|
|
52
72
|
})
|
|
53
73
|
|
|
54
|
-
|
|
74
|
+
this.docs = new DocsStack(this, props)
|
|
55
75
|
|
|
56
|
-
new EmailStack(this, {
|
|
76
|
+
this.email = new EmailStack(this, {
|
|
57
77
|
...props,
|
|
58
|
-
zone: dns.zone,
|
|
78
|
+
zone: this.dns.zone,
|
|
59
79
|
})
|
|
60
80
|
|
|
61
|
-
new RedirectsStack(this, props)
|
|
81
|
+
this.redirects = new RedirectsStack(this, props)
|
|
62
82
|
|
|
63
|
-
new PermissionsStack(this)
|
|
83
|
+
this.permissions = new PermissionsStack(this)
|
|
64
84
|
|
|
65
85
|
// new DashboardStack(this)
|
|
66
86
|
|
|
67
|
-
|
|
87
|
+
this.ai = new AiStack(this, props)
|
|
88
|
+
|
|
89
|
+
this.cli = new CliStack(this, props)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// we use an async init() method here because we need to wait for the
|
|
93
|
+
|
|
94
|
+
async init() {
|
|
68
95
|
if (config.cloud.api?.deploy) {
|
|
69
|
-
|
|
96
|
+
const props = this.props
|
|
97
|
+
this.api = new ComputeStack(this, {
|
|
70
98
|
...props,
|
|
71
|
-
vpc: network.vpc,
|
|
72
|
-
fileSystem: fileSystem.fileSystem,
|
|
73
|
-
zone: dns.zone,
|
|
74
|
-
certificate: security.certificate,
|
|
99
|
+
vpc: this.network.vpc,
|
|
100
|
+
fileSystem: this.fileSystem.fileSystem,
|
|
101
|
+
zone: this.dns.zone,
|
|
102
|
+
certificate: this.security.certificate,
|
|
75
103
|
})
|
|
76
104
|
|
|
77
|
-
new QueueStack(this, {
|
|
105
|
+
this.queue = new QueueStack(this, {
|
|
78
106
|
...props,
|
|
79
|
-
cluster: api.cluster,
|
|
80
|
-
taskDefinition: api.taskDefinition,
|
|
107
|
+
cluster: this.api.cluster,
|
|
108
|
+
taskDefinition: this.api.taskDefinition,
|
|
81
109
|
})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const ai = new AiStack(this, props)
|
|
85
110
|
|
|
86
|
-
|
|
111
|
+
await this.queue.init()
|
|
87
112
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
this.cdn = new CdnStack(this, {
|
|
114
|
+
...props,
|
|
115
|
+
publicBucket: this.storage.publicBucket,
|
|
116
|
+
logBucket: this.storage.logBucket,
|
|
117
|
+
certificate: this.security.certificate,
|
|
118
|
+
firewall: this.security.firewall,
|
|
119
|
+
originRequestFunction: this.docs.originRequestFunction,
|
|
120
|
+
zone: this.dns.zone,
|
|
121
|
+
cliSetupUrl: this.cli.cliSetupUrl,
|
|
122
|
+
askAiUrl: this.ai.askAiUrl,
|
|
123
|
+
summarizeAiUrl: this.ai.summarizeAiUrl,
|
|
124
|
+
lb: this.api?.lb,
|
|
125
|
+
})
|
|
101
126
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
127
|
+
this.deployment = new DeploymentStack(this, {
|
|
128
|
+
...props,
|
|
129
|
+
publicBucket: this.storage.publicBucket,
|
|
130
|
+
privateBucket: this.storage.privateBucket,
|
|
131
|
+
cdn: this.cdn.distribution,
|
|
132
|
+
})
|
|
133
|
+
}
|
|
108
134
|
}
|
|
109
135
|
}
|
package/src/cloud/queue.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { Cluster, TaskDefinition } from 'aws-cdk-lib'
|
|
1
|
+
import type { Cluster, TaskDefinition } from 'aws-cdk-lib/aws-ecs'
|
|
2
2
|
import { aws_ec2 as ec2 } from 'aws-cdk-lib'
|
|
3
3
|
import type { Construct } from 'constructs'
|
|
4
|
+
import { pascalCase, slug } from '@stacksjs/strings'
|
|
5
|
+
import { fs } from '@stacksjs/storage'
|
|
6
|
+
import { path } from '@stacksjs/path'
|
|
4
7
|
import { Rule, Schedule } from 'aws-cdk-lib/aws-events'
|
|
5
8
|
import { EcsTask } from 'aws-cdk-lib/aws-events-targets'
|
|
6
9
|
import type { NestedCloudProps } from '../types'
|
|
@@ -11,19 +14,96 @@ export interface QueueStackProps extends NestedCloudProps {
|
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export class QueueStack {
|
|
17
|
+
scope: Construct
|
|
18
|
+
props: QueueStackProps
|
|
19
|
+
|
|
14
20
|
constructor(scope: Construct, props: QueueStackProps) {
|
|
15
|
-
|
|
21
|
+
this.scope = scope
|
|
22
|
+
this.props = props
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async init() {
|
|
26
|
+
const jobsDir = path.jobsPath()
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const jobFiles = await fs.readdir(jobsDir)
|
|
30
|
+
const actionFiles = await fs.readdir(actionsDir)
|
|
31
|
+
const jobs = []
|
|
32
|
+
|
|
33
|
+
// then, need to loop through all app/Jobs/*.ts and create a rule for each, potentially overwriting the Schedule.ts jobs
|
|
34
|
+
for (const file of jobFiles) {
|
|
35
|
+
if (!file.endsWith('.ts'))
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
const filePath = path.jobsPath(file)
|
|
39
|
+
|
|
40
|
+
// Await the loading of the job module
|
|
41
|
+
jobs.push(await this.loadModule(filePath))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
for (const file of actionFiles) {
|
|
45
|
+
if (!file.endsWith('.ts'))
|
|
46
|
+
continue
|
|
47
|
+
|
|
48
|
+
const filePath = path.actionsPath(file)
|
|
49
|
+
|
|
50
|
+
// Await the loading of the job module
|
|
51
|
+
jobs.push(await this.loadModule(filePath))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
for (const job of jobs)
|
|
55
|
+
await this.createQueueRule(job)
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.error('Error reading the jobs directory:', err)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Helper function to convert a rate string to a cron object for AWS Schedule
|
|
63
|
+
cronScheduleFromRate(rate: string): { minute?: string, hour?: string, month?: string, weekDay?: string, year?: string } {
|
|
64
|
+
// Assuming the rate is in standard cron format, split it to map to the AWS Schedule.cron() parameters
|
|
65
|
+
const parts = rate.split(' ')
|
|
66
|
+
return {
|
|
67
|
+
minute: parts[0],
|
|
68
|
+
hour: parts[1],
|
|
69
|
+
month: parts[2],
|
|
70
|
+
weekDay: parts[3],
|
|
71
|
+
year: parts[4],
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async loadModule(filePath: string) {
|
|
76
|
+
const jobModule = await import(filePath)
|
|
77
|
+
|
|
78
|
+
return jobModule
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
createQueueRule(job: any) {
|
|
82
|
+
// Now you can safely access job.default.rate
|
|
83
|
+
const rate = job.default?.rate
|
|
84
|
+
|
|
85
|
+
// if no rate or job is disabled, no need to schedule, skip
|
|
86
|
+
if (!rate || job.default?.enabled === false)
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
// Convert the rate to a Schedule object
|
|
90
|
+
const schedule = Schedule.cron(this.cronScheduleFromRate(rate))
|
|
91
|
+
|
|
92
|
+
const id = `QueueRule${pascalCase(file.replace('.ts', ''))}`
|
|
93
|
+
|
|
94
|
+
// Perform operations with the jobModule.default as needed
|
|
95
|
+
const rule = new Rule(this.scope, id, {
|
|
16
96
|
// schedule to run every second
|
|
17
|
-
ruleName: `${props.appName}-${props.appEnv}-queue-rule`,
|
|
18
|
-
schedule
|
|
97
|
+
ruleName: `${this.props.appName}-${this.props.appEnv}-queue-rule-${slug(file.replace('.ts', ''))}`,
|
|
98
|
+
schedule,
|
|
19
99
|
})
|
|
20
100
|
|
|
21
101
|
rule.addTarget(new EcsTask({
|
|
22
|
-
cluster: props.cluster,
|
|
23
|
-
taskDefinition: props.taskDefinition,
|
|
102
|
+
cluster: this.props.cluster,
|
|
103
|
+
taskDefinition: this.props.taskDefinition,
|
|
24
104
|
containerOverrides: [
|
|
25
105
|
{
|
|
26
|
-
containerName: `${props.appName}-${props.appEnv}-api`,
|
|
106
|
+
containerName: `${this.props.appName}-${this.props.appEnv}-api`,
|
|
27
107
|
environment: [
|
|
28
108
|
{
|
|
29
109
|
name: 'QUEUE_WORKER',
|
|
@@ -31,13 +111,30 @@ export class QueueStack {
|
|
|
31
111
|
},
|
|
32
112
|
{
|
|
33
113
|
name: 'JOB',
|
|
34
|
-
value:
|
|
114
|
+
value: file,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'JOB_BACKOFF_FACTOR',
|
|
118
|
+
value: jobModule.default?.backoffFactor,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'JOB_RETRIES',
|
|
122
|
+
value: jobModule.default?.tries,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'JOB_INITIAL_DELAY',
|
|
126
|
+
value: jobModule.default?.initialDelay,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'JOB_JITTER',
|
|
130
|
+
value: jobModule.default?.jitter,
|
|
35
131
|
},
|
|
36
132
|
],
|
|
37
133
|
},
|
|
38
134
|
],
|
|
39
135
|
|
|
40
|
-
retryAttempts:
|
|
136
|
+
retryAttempts: 1, // we utilize a custom retry mechanism in the job itself
|
|
137
|
+
// retryAttempts: jobModule.default.tries || 3,
|
|
41
138
|
|
|
42
139
|
subnetSelection: {
|
|
43
140
|
subnetType: ec2.SubnetType.PUBLIC, // SubnetType.PRIVATE_WITH_EGRESS
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stacks-router-layer",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.58",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@stacksjs/router": "^0.58.
|
|
13
|
+
"@stacksjs/router": "^0.58.57"
|
|
14
14
|
}
|
|
15
15
|
}
|