Skip to content

Commit

Permalink
fix(sdk): changing redis empty value to be nil (#3810)
Browse files Browse the repository at this point in the history
fixes [#3493](#3493)
Changing Redis empty value to be nil- before it was js' null, which doesn't have an equivalent in wing, therefore could not be used 

## Checklist

- [x] Title matches [Winglang's style guide](https://www.winglang.io/contributing/start-here/pull_requests#how-are-pull-request-titles-formatted)
- [x] Description explains motivation and solution
- [x] Tests added (always)
- [ ] Docs updated (only required for features)
- [ ] Added `pr/e2e-full` label if this feature requires end-to-end testing

*By submitting this pull request, I confirm that my contribution is made under the terms of the [Wing Cloud Contribution License](https://github.com/winglang/wing/blob/main/CONTRIBUTION_LICENSE.md)*.
  • Loading branch information
tsuf239 authored Aug 15, 2023
1 parent 45970cc commit ecb5bc8
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 34 deletions.
18 changes: 17 additions & 1 deletion examples/tests/valid/redis.w
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ skipPlatforms:
\*/

bring cloud;
bring util;
bring ex;

let r = new ex.Redis();
let r2 = new ex.Redis() as "r2";

test "test" {
let queue = new cloud.Queue();

queue.setConsumer(inflight (message: str) => {
r.set("hello", message);
}, timeout: 3s);

test "testing Redis" {
// Using raw client
let connection = r.rawClient();
connection.set("wing", "does redis");
Expand All @@ -21,4 +28,13 @@ test "test" {
r2.set("wing", "does redis again");
let value2 = r2.get("wing");
assert(value2 == "does redis again");

//With waitUntil
queue.push("world!");

util.waitUntil((): bool => {
return r.get("hello") != nil;
});

assert("world!" == "${r.get("hello")}");
}
2 changes: 1 addition & 1 deletion libs/wingsdk/src/ex/redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export abstract class RedisClientBase implements IRedisClient {

public async get(key: string): Promise<string | undefined> {
let redis = await this.rawClient();
let result = await redis.get(key);
let result = (await redis.get(key)) ?? undefined; // for wing to return nil
return result;
}

Expand Down
4 changes: 2 additions & 2 deletions libs/wingsdk/test/target-sim/redis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ test("can del a value", async () => {
const recordsDeleted = await client.del(key);
const value = await client.get(key);
expect(recordsDeleted).toEqual(1);
expect(value).toEqual(null);
expect(value).toBeUndefined();
});
});

Expand Down Expand Up @@ -130,6 +130,6 @@ test("get a value that does not exist", async () => {
await app._withSimulator(async (s) => {
const client = s.getResource("/my_redis") as ex.IRedisClient;
const value = await client.get(key);
expect(value).toEqual(null);
expect(value).toBeUndefined();
});
});
215 changes: 186 additions & 29 deletions tools/hangar/__snapshots__/test_corpus/valid/redis.w_compile_tf-aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,26 @@

## inflight.$Closure1-1.js
```js
module.exports = function({ $r, $r2 }) {
module.exports = function({ $r }) {
class $Closure1 {
constructor({ }) {
const $obj = (...args) => this.handle(...args);
Object.setPrototypeOf($obj, this);
return $obj;
}
async handle(message) {
(await $r.set("hello",message));
}
}
return $Closure1;
}

```

## inflight.$Closure2-1.js
```js
module.exports = function({ $queue, $r, $r2, $util_Util }) {
class $Closure2 {
constructor({ }) {
const $obj = (...args) => this.handle(...args);
Object.setPrototypeOf($obj, this);
Expand All @@ -17,9 +35,15 @@ module.exports = function({ $r, $r2 }) {
(await $r2.set("wing","does redis again"));
const value2 = (await $r2.get("wing"));
{((cond) => {if (!cond) throw new Error("assertion failed: value2 == \"does redis again\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })(value2,"does redis again")))};
(await $queue.push("world!"));
(await $util_Util.waitUntil(async () => {
return ((await $r.get("hello")) !== undefined);
}
));
{((cond) => {if (!cond) throw new Error("assertion failed: \"world!\" == \"${r.get(\"hello\")}\"")})((((a,b) => { try { return require('assert').deepStrictEqual(a,b) === undefined; } catch { return false; } })("world!",String.raw({ raw: ["", ""] }, (await $r.get("hello"))))))};
}
}
return $Closure1;
return $Closure2;
}

```
Expand All @@ -45,7 +69,7 @@ module.exports = function({ $r, $r2 }) {
},
"output": {
"WING_TEST_RUNNER_FUNCTION_ARNS": {
"value": "[[\"root/Default/Default/test:test\",\"${aws_lambda_function.testtest_Handler_295107CC.arn}\"]]"
"value": "[[\"root/Default/Default/test:testing Redis\",\"${aws_lambda_function.testtestingRedis_Handler_7678DD27.arn}\"]]"
}
},
"provider": {
Expand Down Expand Up @@ -131,38 +155,67 @@ module.exports = function({ $r, $r2 }) {
}
},
"aws_iam_role": {
"testtest_Handler_IamRole_15693C93": {
"cloudQueue-SetConsumer-cdafee6e_IamRole_2548D828": {
"//": {
"metadata": {
"path": "root/Default/Default/test:test/Handler/IamRole",
"uniqueId": "testtest_Handler_IamRole_15693C93"
"path": "root/Default/Default/cloud.Queue-SetConsumer-cdafee6e/IamRole",
"uniqueId": "cloudQueue-SetConsumer-cdafee6e_IamRole_2548D828"
}
},
"assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Effect\":\"Allow\"}]}"
},
"testtestingRedis_Handler_IamRole_8B9140DE": {
"//": {
"metadata": {
"path": "root/Default/Default/test:testing Redis/Handler/IamRole",
"uniqueId": "testtestingRedis_Handler_IamRole_8B9140DE"
}
},
"assume_role_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Effect\":\"Allow\"}]}"
}
},
"aws_iam_role_policy": {
"testtest_Handler_IamRolePolicy_AF0279BD": {
"cloudQueue-SetConsumer-cdafee6e_IamRolePolicy_37133937": {
"//": {
"metadata": {
"path": "root/Default/Default/cloud.Queue-SetConsumer-cdafee6e/IamRolePolicy",
"uniqueId": "cloudQueue-SetConsumer-cdafee6e_IamRolePolicy_37133937"
}
},
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"sqs:ReceiveMessage\",\"sqs:ChangeMessageVisibility\",\"sqs:GetQueueUrl\",\"sqs:DeleteMessage\",\"sqs:GetQueueAttributes\"],\"Resource\":[\"${aws_sqs_queue.cloudQueue.arn}\"],\"Effect\":\"Allow\"},{\"Action\":[\"elasticache:Describe*\"],\"Resource\":[\"${aws_elasticache_cluster.exRedis_RedisCluster_3C9A5882.arn}\"],\"Effect\":\"Allow\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"}]}",
"role": "${aws_iam_role.cloudQueue-SetConsumer-cdafee6e_IamRole_2548D828.name}"
},
"testtestingRedis_Handler_IamRolePolicy_21FBAD46": {
"//": {
"metadata": {
"path": "root/Default/Default/test:test/Handler/IamRolePolicy",
"uniqueId": "testtest_Handler_IamRolePolicy_AF0279BD"
"path": "root/Default/Default/test:testing Redis/Handler/IamRolePolicy",
"uniqueId": "testtestingRedis_Handler_IamRolePolicy_21FBAD46"
}
},
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"elasticache:Describe*\"],\"Resource\":[\"${aws_elasticache_cluster.exRedis_RedisCluster_3C9A5882.arn}\"],\"Effect\":\"Allow\"},{\"Action\":[\"elasticache:Describe*\"],\"Resource\":[\"${aws_elasticache_cluster.r2_RedisCluster_C6087F40.arn}\"],\"Effect\":\"Allow\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"}]}",
"role": "${aws_iam_role.testtest_Handler_IamRole_15693C93.name}"
"policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"elasticache:Describe*\"],\"Resource\":[\"${aws_elasticache_cluster.exRedis_RedisCluster_3C9A5882.arn}\"],\"Effect\":\"Allow\"},{\"Action\":[\"elasticache:Describe*\"],\"Resource\":[\"${aws_elasticache_cluster.r2_RedisCluster_C6087F40.arn}\"],\"Effect\":\"Allow\"},{\"Action\":[\"sqs:SendMessage\"],\"Resource\":[\"${aws_sqs_queue.cloudQueue.arn}\"],\"Effect\":\"Allow\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"},{\"Effect\":\"Allow\",\"Action\":[\"ec2:CreateNetworkInterface\",\"ec2:DescribeNetworkInterfaces\",\"ec2:DeleteNetworkInterface\",\"ec2:DescribeSubnets\",\"ec2:DescribeSecurityGroups\"],\"Resource\":\"*\"}]}",
"role": "${aws_iam_role.testtestingRedis_Handler_IamRole_8B9140DE.name}"
}
},
"aws_iam_role_policy_attachment": {
"testtest_Handler_IamRolePolicyAttachment_ADF4752D": {
"cloudQueue-SetConsumer-cdafee6e_IamRolePolicyAttachment_45079F65": {
"//": {
"metadata": {
"path": "root/Default/Default/test:test/Handler/IamRolePolicyAttachment",
"uniqueId": "testtest_Handler_IamRolePolicyAttachment_ADF4752D"
"path": "root/Default/Default/cloud.Queue-SetConsumer-cdafee6e/IamRolePolicyAttachment",
"uniqueId": "cloudQueue-SetConsumer-cdafee6e_IamRolePolicyAttachment_45079F65"
}
},
"policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"role": "${aws_iam_role.testtest_Handler_IamRole_15693C93.name}"
"role": "${aws_iam_role.cloudQueue-SetConsumer-cdafee6e_IamRole_2548D828.name}"
},
"testtestingRedis_Handler_IamRolePolicyAttachment_4A5E3F4E": {
"//": {
"metadata": {
"path": "root/Default/Default/test:testing Redis/Handler/IamRolePolicyAttachment",
"uniqueId": "testtestingRedis_Handler_IamRolePolicyAttachment_4A5E3F4E"
}
},
"policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"role": "${aws_iam_role.testtestingRedis_Handler_IamRole_8B9140DE.name}"
}
},
"aws_internet_gateway": {
Expand All @@ -179,29 +232,74 @@ module.exports = function({ $r, $r2 }) {
"vpc_id": "${aws_vpc.VPC.id}"
}
},
"aws_lambda_event_source_mapping": {
"cloudQueue_EventSourceMapping_41814136": {
"//": {
"metadata": {
"path": "root/Default/Default/cloud.Queue/EventSourceMapping",
"uniqueId": "cloudQueue_EventSourceMapping_41814136"
}
},
"batch_size": 1,
"event_source_arn": "${aws_sqs_queue.cloudQueue.arn}",
"function_name": "${aws_lambda_function.cloudQueue-SetConsumer-cdafee6e.function_name}"
}
},
"aws_lambda_function": {
"testtest_Handler_295107CC": {
"cloudQueue-SetConsumer-cdafee6e": {
"//": {
"metadata": {
"path": "root/Default/Default/cloud.Queue-SetConsumer-cdafee6e/Default",
"uniqueId": "cloudQueue-SetConsumer-cdafee6e"
}
},
"environment": {
"variables": {
"REDIS_CLUSTER_ID_89baf91f": "${aws_elasticache_cluster.exRedis_RedisCluster_3C9A5882.cluster_id}",
"WING_FUNCTION_NAME": "cloud-Queue-SetConsumer-cdafee6e-c8eb6a09",
"WING_TARGET": "tf-aws"
}
},
"function_name": "cloud-Queue-SetConsumer-cdafee6e-c8eb6a09",
"handler": "index.handler",
"publish": true,
"role": "${aws_iam_role.cloudQueue-SetConsumer-cdafee6e_IamRole_2548D828.arn}",
"runtime": "nodejs18.x",
"s3_bucket": "${aws_s3_bucket.Code.bucket}",
"s3_key": "${aws_s3_object.cloudQueue-SetConsumer-cdafee6e_S3Object_8868B9FB.key}",
"timeout": 3,
"vpc_config": {
"security_group_ids": [
"${aws_security_group.exRedis_securityGroup_3948C3F2.id}"
],
"subnet_ids": [
"${aws_subnet.PrivateSubnet.id}"
]
}
},
"testtestingRedis_Handler_7678DD27": {
"//": {
"metadata": {
"path": "root/Default/Default/test:test/Handler/Default",
"uniqueId": "testtest_Handler_295107CC"
"path": "root/Default/Default/test:testing Redis/Handler/Default",
"uniqueId": "testtestingRedis_Handler_7678DD27"
}
},
"environment": {
"variables": {
"QUEUE_URL_31e95cbd": "${aws_sqs_queue.cloudQueue.url}",
"REDIS_CLUSTER_ID_30c8c4ae": "${aws_elasticache_cluster.r2_RedisCluster_C6087F40.cluster_id}",
"REDIS_CLUSTER_ID_89baf91f": "${aws_elasticache_cluster.exRedis_RedisCluster_3C9A5882.cluster_id}",
"WING_FUNCTION_NAME": "Handler-c8f4f2a1",
"WING_FUNCTION_NAME": "Handler-c8775e77",
"WING_TARGET": "tf-aws"
}
},
"function_name": "Handler-c8f4f2a1",
"function_name": "Handler-c8775e77",
"handler": "index.handler",
"publish": true,
"role": "${aws_iam_role.testtest_Handler_IamRole_15693C93.arn}",
"role": "${aws_iam_role.testtestingRedis_Handler_IamRole_8B9140DE.arn}",
"runtime": "nodejs18.x",
"s3_bucket": "${aws_s3_bucket.Code.bucket}",
"s3_key": "${aws_s3_object.testtest_Handler_S3Object_9F4E28A7.key}",
"s3_key": "${aws_s3_object.testtestingRedis_Handler_S3Object_3AE6E27A.key}",
"timeout": 30,
"vpc_config": {
"security_group_ids": [
Expand Down Expand Up @@ -326,11 +424,22 @@ module.exports = function({ $r, $r2 }) {
}
},
"aws_s3_object": {
"testtest_Handler_S3Object_9F4E28A7": {
"cloudQueue-SetConsumer-cdafee6e_S3Object_8868B9FB": {
"//": {
"metadata": {
"path": "root/Default/Default/cloud.Queue-SetConsumer-cdafee6e/S3Object",
"uniqueId": "cloudQueue-SetConsumer-cdafee6e_S3Object_8868B9FB"
}
},
"bucket": "${aws_s3_bucket.Code.bucket}",
"key": "<ASSET_KEY>",
"source": "<ASSET_SOURCE>"
},
"testtestingRedis_Handler_S3Object_3AE6E27A": {
"//": {
"metadata": {
"path": "root/Default/Default/test:test/Handler/S3Object",
"uniqueId": "testtest_Handler_S3Object_9F4E28A7"
"path": "root/Default/Default/test:testing Redis/Handler/S3Object",
"uniqueId": "testtestingRedis_Handler_S3Object_3AE6E27A"
}
},
"bucket": "${aws_s3_bucket.Code.bucket}",
Expand Down Expand Up @@ -420,6 +529,17 @@ module.exports = function({ $r, $r2 }) {
"vpc_id": "${aws_vpc.VPC.id}"
}
},
"aws_sqs_queue": {
"cloudQueue": {
"//": {
"metadata": {
"path": "root/Default/Default/cloud.Queue/Default",
"uniqueId": "cloudQueue"
}
},
"name": "cloud-Queue-c86e03d8"
}
},
"aws_subnet": {
"PrivateSubnet": {
"//": {
Expand Down Expand Up @@ -475,6 +595,7 @@ const $outdir = process.env.WING_SYNTH_DIR ?? ".";
const $wing_is_test = process.env.WING_IS_TEST === "true";
const std = $stdlib.std;
const cloud = $stdlib.cloud;
const util = $stdlib.util;
const ex = $stdlib.ex;
class $Root extends $stdlib.std.Resource {
constructor(scope, id) {
Expand All @@ -489,7 +610,6 @@ class $Root extends $stdlib.std.Resource {
return $stdlib.core.NodeJsCode.fromInline(`
require("./inflight.$Closure1-1.js")({
$r: ${context._lift(r)},
$r2: ${context._lift(r2)},
})
`);
}
Expand All @@ -506,15 +626,52 @@ class $Root extends $stdlib.std.Resource {
}
_registerBind(host, ops) {
if (ops.includes("handle")) {
$Closure1._registerBindObject(r, host, ["rawClient"]);
$Closure1._registerBindObject(r2, host, ["get", "set"]);
$Closure1._registerBindObject(r, host, ["set"]);
}
super._registerBind(host, ops);
}
}
class $Closure2 extends $stdlib.std.Resource {
constructor(scope, id, ) {
super(scope, id);
this._addInflightOps("handle", "$inflight_init");
this.display.hidden = true;
}
static _toInflightType(context) {
return $stdlib.core.NodeJsCode.fromInline(`
require("./inflight.$Closure2-1.js")({
$queue: ${context._lift(queue)},
$r: ${context._lift(r)},
$r2: ${context._lift(r2)},
$util_Util: ${context._lift(util.Util)},
})
`);
}
_toInflight() {
return $stdlib.core.NodeJsCode.fromInline(`
(await (async () => {
const $Closure2Client = ${$Closure2._toInflightType(this).text};
const client = new $Closure2Client({
});
if (client.$inflight_init) { await client.$inflight_init(); }
return client;
})())
`);
}
_registerBind(host, ops) {
if (ops.includes("handle")) {
$Closure2._registerBindObject(queue, host, ["push"]);
$Closure2._registerBindObject(r, host, ["get", "rawClient"]);
$Closure2._registerBindObject(r2, host, ["get", "set"]);
}
super._registerBind(host, ops);
}
}
const r = this.node.root.newAbstract("@winglang/sdk.ex.Redis",this,"ex.Redis");
const r2 = this.node.root.newAbstract("@winglang/sdk.ex.Redis",this,"r2");
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:test",new $Closure1(this,"$Closure1"));
const queue = this.node.root.newAbstract("@winglang/sdk.cloud.Queue",this,"cloud.Queue");
(queue.setConsumer(new $Closure1(this,"$Closure1"),{ timeout: (std.Duration.fromSeconds(3)) }));
this.node.root.new("@winglang/sdk.std.Test",std.Test,this,"test:testing Redis",new $Closure2(this,"$Closure2"));
}
}
const $App = $stdlib.core.App.for(process.env.WING_TARGET);
Expand Down
Loading

0 comments on commit ecb5bc8

Please sign in to comment.