Programming

I’m working on a tricky problem right now for our auctions app and thinking through what automated coding bot could do and couldn’t do as I go along. Here’s a summary:

Basically I need to send an email to to everyone who won an item(s) just after the auction has ended. I have the function that sends the emails. But to schedule it to happen when the auction ends, I need to be able to create, update and remove an AWS scheduler programmatically from the auctions app. (I’ll explain why I can’t just use the app to do it below).

I used ChatGPT to get create some basic lambda handler code to programmatically interact with AWS EventBridge. I even used it to explain to me what the roleArn property should be, how to create the role, what permission and trust relationship to assign. I was surprised that it was able to do this. IAM is always so damn confusing to me - what’s the source, what’s the target, should I create a new role just for this, should I used a managed permission set or roll my own, etc.

So kudos to ChatGPT on that. But here’s all the stuff so far that I think still needs a human to figure out and I don’t see how copilot or whatever could ever realistically decide. Also, not coincidentally, these are the kinds of decisions a junior programmer could really go down the wrong path with and make a mess of.

  1. Why not just have the app trigger itself to send the emails when the auction is done? It’s because we’re using AWS AppSync, which is really just a collection of lambdas, which are just inert functions that get executed at run time. There’s no running server to run some kind of internal chron job with.

  2. How to solve this? My first idea was just to have a simple node server running on the side that could interact with AppSync and trigger the emails to send at a specific time. But that would involve creating some kind of EC2 instance, either through Elastic Beanstalk, or manually, and a bunch of other permissions and communication type stuff I didn’t feel like dealing with. I do everything I can to avoid having servers to babysit.

  3. Another solution that might appeal to a junior developer is to have the admin user’s browser trigger the end of auction. But of course that requires that an admin user have their browser open at the right time, and would be a very bad idea imo.

  4. So I decided to go with the scheduler, even though it’s scary because there are a ton of moving parts, and sending out these emails to a bunch of people before the auction is over could be very bad. Which means and I need good integration tests that create an auction from whole cloth, have fake users bid on stuff, end the auction and make sure the emails go out (using Pop3 to connect to Gmail test accounts). Luckily I already have all that stuff in place. But good luck having ChatGPT tell you how to set it all up.

  5. How to interact with the scheduler? Apparently AppSync can talk to AWS EventBridge directly. But that spooks me a little because the AppSync functions and resolvers only allow a small subset of Javascript—including not allowing the ‘new’ keyword, which makes dealing with dates and time zones a gigantic PITA. Also the AppSync logs mush everything together for each request, which is getting harder and harder to trace as our app gets more complicated. So instead I have AppSync talk to a lambda that talks to EventBridge. That way if we have some crisis in real time after the auction ends, or during it, I can quickly go to the dedicated lambda logs to see what’s going on.

  6. EventBridge has separate functions for CreateSchedule and UpdateSchedule. It’s not super easy to tell if the schedule has already been created or not. So should I go through extra hoops to detect if a schedule already exists for this auction, or just delete any existing schedule and create a new one? I went with the latter but I haven’t got it working yet. If I run into weirdness (like time lags for deleting, which AWS does for some resources) I may need to revert to the first method. Also trying to delete a non-existent schedule and then catching the error will work, but it’s kind of code smelly imo.

  7. Which logic should go into the AppSync function that calls the lambda and which should go into the lambda itself. IE - how generic should I try to make the lambda? Should it be able to schedule anything for any app? Should it be able to schedule anything, but just for the auction app? Should it be able to only schedule the end of auction event for the auction app?

  8. I went with the last thing. I’ve found that trying to make things too generic too early just leads to pain down the road, because inevitably you assume a bunch of stuff that you don’t need, and find out you need stuff you didn’t consider.

  9. In general, I’ve found it much easier to just make the thing very specific the first time, then worry about sharing code when you have a second use case, and maybe not even then. Instead of DRY (don’t repeat yourself), I prefer WET (write everything twice). Then maybe the 3rd time think about creating some new layer of abstraction or mechanism to share the code/function. This is something that it usually takes junior developers a long time to figure out. Some never seem to and are always trying to write the perfect abstraction, then getting endlessly frustrated when future requirements throw a monkey wrench into their beautiful crystalline design. I’ve found it at least an order of magnitude easier to add a new layer of abstraction later than remove an unneeded one. Your boss finds this out when they ask you for a new feature on a mature app you created and you go into a conniption fit about how hard it will be, or you say no problem, we can do that pretty easily.

Anyway this is just a sliver of the thought process I’ve had on this so far, and I haven’t finished coding it yet. It’s why I don’t worry about Copilot taking my job for the near future at least. I spend about 90% of my dev time thinking about stuff like this and 10% actually typing out code on the keyboard, if that.

Oh yeah, and I did have to spend some extra time down a typical AWS cryptic error message rabbit hole because ChatGPT was adamant I needed to add a ‘Z’ to the end of the timestamp (ISO minus milliseconds), when the Z definitely should not be there. So there’s always that.

2 Likes