@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 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
- const rule = new Rule(scope, "QueueRule", {
1804
- ruleName: `${props.appName}-${props.appEnv}-queue-rule`,
1805
- schedule: Schedule.cron({ minute: "*", hour: "*", month: "*", weekDay: "*", year: "*" })
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: "DummyJob.ts"
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: 3,
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
- const dns2 = new DnsStack(this, props);
1838
- const security2 = new SecurityStack(this, {
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: dns2.zone
1928
+ zone: this.dns.zone
1841
1929
  });
1842
- const storage5 = new StorageStack(this, {
1930
+ this.storage = new StorageStack(this, {
1843
1931
  ...props,
1844
- kmsKey: security2.kmsKey
1932
+ kmsKey: this.security.kmsKey
1845
1933
  });
1846
- const network2 = new NetworkStack(this, props);
1847
- const fileSystem = new FileSystemStack(this, {
1934
+ this.network = new NetworkStack(this, props);
1935
+ this.fileSystem = new FileSystemStack(this, {
1848
1936
  ...props,
1849
- vpc: network2.vpc
1937
+ vpc: this.network.vpc
1850
1938
  });
1851
- new JumpBoxStack(this, {
1939
+ this.jumpBox = new JumpBoxStack(this, {
1852
1940
  ...props,
1853
- vpc: network2.vpc,
1854
- fileSystem: fileSystem.fileSystem
1941
+ vpc: this.network.vpc,
1942
+ fileSystem: this.fileSystem.fileSystem
1855
1943
  });
1856
- const docs2 = new DocsStack(this, props);
1857
- new EmailStack(this, {
1944
+ this.docs = new DocsStack(this, props);
1945
+ this.email = new EmailStack(this, {
1858
1946
  ...props,
1859
- zone: dns2.zone
1947
+ zone: this.dns.zone
1860
1948
  });
1861
- new RedirectsStack(this, props);
1862
- new PermissionsStack(this);
1863
- let api;
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
- api = new ComputeStack(this, {
1956
+ const props = this.props;
1957
+ this.api = new ComputeStack(this, {
1866
1958
  ...props,
1867
- vpc: network2.vpc,
1868
- fileSystem: fileSystem.fileSystem,
1869
- zone: dns2.zone,
1870
- certificate: security2.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.56",
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.507.0",
59
- "@aws-sdk/client-cloudformation": "^3.507.0",
60
- "@aws-sdk/client-cloudfront": "^3.507.0",
61
- "@aws-sdk/client-cloudwatch-logs": "^3.508.0",
62
- "@aws-sdk/client-ec2": "^3.507.0",
63
- "@aws-sdk/client-efs": "^3.507.0",
64
- "@aws-sdk/client-iam": "^3.507.0",
65
- "@aws-sdk/client-lambda": "^3.507.0",
66
- "@aws-sdk/client-route-53-domains": "^3.507.0",
67
- "@aws-sdk/client-s3": "^3.507.0",
68
- "@aws-sdk/client-ses": "^3.507.0",
69
- "@aws-sdk/client-sesv2": "^3.507.0",
70
- "@aws-sdk/client-ssm": "^3.507.0",
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.507.0",
83
- "@aws-sdk/client-cloudformation": "^3.507.0",
84
- "@aws-sdk/client-cloudfront": "^3.507.0",
85
- "@aws-sdk/client-cloudwatch-logs": "^3.508.0",
86
- "@aws-sdk/client-dynamodb": "3.507.0",
87
- "@aws-sdk/client-ec2": "^3.507.0",
88
- "@aws-sdk/client-efs": "^3.507.0",
89
- "@aws-sdk/client-iam": "^3.507.0",
90
- "@aws-sdk/client-lambda": "^3.507.0",
91
- "@aws-sdk/client-route-53-domains": "^3.507.0",
92
- "@aws-sdk/client-s3": "^3.507.0",
93
- "@aws-sdk/client-ses": "^3.507.0",
94
- "@aws-sdk/client-sesv2": "^3.507.0",
95
- "@aws-sdk/client-ssm": "^3.507.0",
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.53",
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.53",
9
+ "version": "0.58.57",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "aws-sdk": "^2.1552.0"
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.1552.0",
28
- "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1552.0.tgz",
29
- "integrity": "sha512-sRuzlCeSHXUsdLqsV/E+nPrgBn1EI3BoA38D5qfNMRcPTd9j4G8M4AyMymKyNxLoWOKLqz7xFBa801MHflGwEg==",
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.56",
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.1552.0"
13
+ "aws-sdk": "^2.1553.0"
14
14
  }
15
15
  }
@@ -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
- // please beware: be careful changing the order of the stack creations below
29
- const dns = new DnsStack(this, props)
46
+ this.scope = scope
47
+ this.props = props
30
48
 
31
- const security = new SecurityStack(this, {
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
- const storage = new StorageStack(this, {
56
+ this.storage = new StorageStack(this, {
37
57
  ...props,
38
- kmsKey: security.kmsKey,
58
+ kmsKey: this.security.kmsKey,
39
59
  })
40
60
 
41
- const network = new NetworkStack(this, props)
61
+ this.network = new NetworkStack(this, props)
42
62
 
43
- const fileSystem = new FileSystemStack(this, {
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
- const docs = new DocsStack(this, props)
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
- let api
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
- api = new ComputeStack(this, {
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
- const cli = new CliStack(this, props)
111
+ await this.queue.init()
87
112
 
88
- const cdn = new CdnStack(this, {
89
- ...props,
90
- publicBucket: storage.publicBucket,
91
- logBucket: storage.logBucket,
92
- certificate: security.certificate,
93
- firewall: security.firewall,
94
- originRequestFunction: docs.originRequestFunction,
95
- zone: dns.zone,
96
- cliSetupUrl: cli.cliSetupUrl,
97
- askAiUrl: ai.askAiUrl,
98
- summarizeAiUrl: ai.summarizeAiUrl,
99
- lb: api?.lb,
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
- new DeploymentStack(this, {
103
- ...props,
104
- publicBucket: storage.publicBucket,
105
- privateBucket: storage.privateBucket,
106
- cdn: cdn.distribution,
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
  }
@@ -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
- const rule = new Rule(scope, 'QueueRule', {
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: Schedule.cron({ minute: '*', hour: '*', month: '*', weekDay: '*', year: '*' }),
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: 'DummyJob.ts',
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: 3,
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.56",
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.53"
13
+ "@stacksjs/router": "^0.58.57"
14
14
  }
15
15
  }