Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SET and other command questions #1

Open
mergesort opened this issue May 2, 2023 · 5 comments
Open

SET and other command questions #1

mergesort opened this issue May 2, 2023 · 5 comments

Comments

@mergesort
Copy link

Hi @AndrewBarba, I'm not sure if it's intentional but your timing on releasing an Upstash client couldn't have been more perfect with Vercel's release today. I was playing around with it in a project and was wondering what the right way to SET keys/values was, and if your client was intended for that or just for GET commands.

I imagine that since this is really new it might not have or support all of the Redis functions Upstash supports. Is the right thing to do when a command isn't available to call exec?

Thanks a lot for the library, really looking forward to setting this up in a small project of mine. 🙂

@AndrewBarba
Copy link
Contributor

AndrewBarba commented May 2, 2023

I will admit, the timing was nice! This library supports every Redis command via exec() but after some testing I can see the API is not ideal as some Redis commands always return String values and that makes this clunky to work with. I'm going to make some API updates later today that make things much cleaner.

In the mean time here are some examples of setting keys:

// SET
// status === "OK" on all set commands
let status: String = try await kv.exec("set", "foo", "5")

// GET
// Redis returns a string value even though its underlying value is an Int. I will make this easier to work with
// val === "5"
let val: String = try await kv.get("foo")

// INCR
// Notice this api really does return an Int because it's using a math function
let visits: Int = try await kv.exec("incr", "visits")

@AndrewBarba
Copy link
Contributor

AndrewBarba commented May 2, 2023

@mergesort Take a look at this PR, I think it makes things much nicer to work with: #2

@mergesort
Copy link
Author

Hey Andrew, I finally got a chance to try this out. The new API looks great, but I can't seem to get the commands actually working. Quite likely I'm doing something wrong, but this is the entirety of my server.

@main
struct App: ExpressHandler {
    static let client = RedisClient(hostname: "https://us1-xyz-abc-39234.upstash.io", token: "not-for-your-eyes")

    static let router = Router()
        .get("/hello", { req, res in
            res.status(.ok).send("Hello, Upstash")
        })
        .get("/hello/:name", { req, res in
            res.send("Hello, " + req.pathParams["name"]!)
        })
        .get("/get/:key", { req, res in
            guard let key = req.pathParams["key"] else { return res.status(400) }
            let val = try await Self.client.get(key).decode(String.self)

            return res.send(val)
        })
        .get("/set/:key/:value") { req, res in
            guard let key = req.pathParams["key"] else { return res.status(400) }

            let result = try await Self.client.set(key, req.pathParams["value"])
            return res.status(.ok).send(result.string ?? "null")
        }
}

The /hello and /hello/:name endpoints work perfectly fine but the get/:key and set/:key/:value endpoints both return an Internal Server Error in the browser.

This is the error returned in the console.

2023-05-07T16:10:57-0400 warning Lambda : lifecycleIteration=1 [AWSLambdaRuntimeCore] lambda handler returned an error: RedisError(error: "Unauthorized")
  RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: undefined
    at new NodeError (internal/errors.js:322:7)
    at ServerResponse.writeHead (_http_server.js:259:11)
    at Server.<anonymous> (/Users/mergesort/Desktop/Upstashio/.build/checkouts/Vercel/Plugins/VercelPackager/Server/server.js:37:9)
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  code: 'ERR_HTTP_INVALID_STATUS_CODE'
}

Any thoughts as to what I could be doing wrong?

@AndrewBarba
Copy link
Contributor

@mergesort Based on RedisError(error: "Unauthorized") in the stack trace, looks like you used a bad token or hostname for your client. I pasted your exact code into my project running on vercel and it worked fine:

➜  vercel-starter-kit git:(kv) ✗ curl http://localhost:7676/set/foo/bar
OK%
➜  vercel-starter-kit git:(kv) ✗ curl http://localhost:7676/get/foo
"bar"%
import Vercel
import Upstash

let kv = RedisClient(
    hostname: Vercel.Environment["KV_REST_API_URL"]!,
    token: Vercel.Environment["KV_REST_API_TOKEN"]!
)

@main
struct App: ExpressHandler {

    static let router = Router()
        .get("/hello", { req, res in
            res.status(.ok).send("Hello, Upstash")
        })
        .get("/hello/:name", { req, res in
            res.send("Hello, " + req.pathParams["name"]!)
        })
        .get("/get/:key", { req, res in
            guard let key = req.pathParams["key"] else { return res.status(400) }
            let val = try await kv.get(key).decode(String.self)

            return res.send(val)
        })
        .get("/set/:key/:value") { req, res in
            guard let key = req.pathParams["key"] else { return res.status(400) }

            let result = try await kv.set(key, req.pathParams["value"])
            return res.status(.ok).send(result.string ?? "null")
        }
}

@mergesort
Copy link
Author

Ah, after seeing that the error is unauthorized I noticed that Upstash seems to have three notions of passwords.

  1. The redis database password.

Screenshot 2023-05-07 at 17 17 26

2 & 3. Two tokens for reading & writing using the Upstash API.

Screenshot 2023-05-07 at 17 19 38

Since they're obfuscated as *** I didn't even think that there would be a difference, and I was using the database password when I should have been using Upstash's token. Now everything is working great, and I can confirm that the API you've created works great.

Thank you so much for another great library, I have some fun ideas that I can't wait to experiment with. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants