How I Wasted 6 Months Creating Disgo
While planning the creation of a community, I needed a way to implement effective moderation; among other automated tasks. Using the Application Programming Interface (API) provided by a messaging platform would allow me to implement these features in a Chat Bot. To be specific, an API represents a definition on HOW to communicate (from computer to computer) within a network. A Chat Bot is an application that communicates by making requests (from one computer to another) to use an API. An application (that is run on a computer) makes requests by executing code (created in a programming language). The code of an application that makes requests to an API is called the API Wrapper.
Discord is a messaging platform which has permissions for moderation purposes, communication channels, threads, forums, voice chats, screen sharing, events, and the ability to automate via an API. Discord alternatives include TeamSpeak, Matrix, Harmony, and Guilded. However, none of these platforms are as feature-rich as Discord yet; with the exception of Guilded which lacks an official Bot API. In addition, I have used Discord since 2016. As a result, I decided to use Discord as a messaging platform for my community.
This choice is significant because a Discord Bot is a server-side software (that operates in a distributed system). In addition, the programming language choice defines the API Wrapper options. For example, I was not using NodeJS, so using the DiscordJS API Wrapper was not a viable option (regardless of its issues). Go has multiple Discord API Wrapper implementations, but I would find these to be sub-par (explained in the Project Timeline). As a result, I needed to create a Discord API Wrapper for Go to create a Discord Bot (in Go).
Create a feature-complete yet maintainable Discord API Wrapper for Go.
What is Dasgo?
Dasgo provides a direct representation of Discord API Objects in Go. Using
dasgo to generate or alias the structs of a Discord API wrapper or bot saves developers from maintaining over 3500 lines of Go code. As
dasgo gains adoption, users will benefit from code that is reviewed by more people and updated quickly.
What is Disgo?
Disgo is a Discord API Wrapper designed to be flexible, performant, secure, and thread-safe. Disgo aims to provide every feature in the Discord API along with optional caching, shard management, rate limiting, and logging. Disgo is also the only Go module to provide a 100% one-to-one implementation of the Discord API.
The features and capabilities of Disgo are easier to understand by considering the limitations of the current Discord API Wrappers.
Go API Wrappers
With regards to performance, Disgo is the only Go Discord API Wrapper that doesn't use reflection in its hot-paths (aka main functionality; requests, events). A precise selection of dependencies (explained in library decisions) allow Disgo to maintain the most performant code.
Synchronized memory pools are used for objects that are constantly created. Disgo's cache is optional. In a future release,
fieldalignment will be used to save memory on otherwise large structs (defined by the Discord API). As a result, Disgo does not require as much memory as cache-first Go API Wrappers, nor does it invoke the Garbage Collector as frequently.
Disgo is the only Go API Wrapper using a maintainable approach to achieve feature completion. Disgo is the only wrapper to define API definitions (objects, requests, commands) as structs, allowing for usage of the Discord Producer API without requiring knowledge of an additional API Wrapper Consumer API. Disgo is also the only Go API Wrapper to provide OAuth2 flows.
The following information includes a direct comparison of Disgo to a Go API Wrapper library.
NOTE: I am a DiscordGo contributor.
- Cache First
- Cache First
Other API Wrappers (Non-Language Specific)
Disgo is the only Discord API Wrapper to feature Automatic Intent Calculation (for the Discord Gateway) and will be the only API Wrapper to support an optimal implementation of every Discord Rate Limit (upon a clarification by Discord).
Disgo `v0.10.0` is a BETA version. For more information, read the State of Disgo (v0.10.0). Contribute to Disgo by reading the roadmap. This article will be updated upon the release of an official version.
Whenever you scroll down to the footer of certain websites, you'll see a phrase that says, "made with love" or some boolshet like that. This project timeline is the opposite because this project is what made me realize that everything I do is motivated by anger. This is a project timeline of a boy becoming a man by creating a project that took 150 people 7 years... within 6 months. Here lies my journey in creating the most performant feature-complete Discord API Wrapper in Go, while learning about everything that is wrong with the software development industry.
Looking back I've realized that people I'm surrounded by haven't been the best influence. I wanted to host a community because the people I interact with from my channel are awesome. The Earth has multiple sides and I've spent most of my time with people who laugh at kids being shot down while the shooter streams Doom. However, there is a side of Earth out there full of people whose life is peaceful. I have been aware of these people from my youth, but my upbringing led me to pick the wrong side. As a result, I must exert effort to connect with peaceful people.
The API Wrapper
I created the Discord Server (called a guild) for the community on March 1st, 2022. I would spend the following days adding as much functionality as I could without programming. There are many ways to solve a problem and programming is simply one tool to do so. Once it was time to implement custom functionality, I looked into three Discord API Wrappers created for Go. Unfortunately, I'd quickly find out all the issues these wrappers had, explained in the previous section. For more information, read the State of Disgo (v0.10.0); which includes a summary of my initial findings.
I would use the DiscordGo library for a few days until I encountered a few errors. I attempted to solve these through multiple issues and pull requests, but the promise (read: limitation) of Backwards Compatibility was enough to recognize that these changes would fall short in some way. In addition, Russia (where the maintainers live) was being sanctioned. At this point, the decision was obvious.
Use DJS. DiscordJS has issues. Instead, I decided that I would create a Discord API Wrapper for Go that didn't have any of these problems. Besides, Discord was a company worth $15 billion baller dollers. How hard could this be?
I reached out to over 10 people (including 4 women) and asked if they wanted to assist with this task. 3 men gave me the ol' Wagie World homework excuse while the others ghosted me like the response a company gives an r/programmerhumor user. Fine. Have fun being L3... That left Thomas — a college student — and Daniel, who I worked with on 11503 Hyperfang: Rover Ruckus, Audius Enhanced, and a Failed Startup.
We start the project on March 20th and... Fuck.
Every problem I experience going forward is only an issue with people. That's because programming is a product of humans built upon by other humans. To be specific, I experienced problems with Discord employees — who get paid to be extremely inefficient — and the entire wagie world that follows.
The first person to cause problems is Daniel.
On April 16, I started to troll the Go issue tracker by submitting fundamentally valid error proposals using meme language. Everyone knows that error handling is a psyop implemented by Russ Cox himself to scam Google into spending millions per year on Generics. Don't believe me?
He got paid 1.2m a year to ignore the languages most voted problem (since Generics passed) when his proposal failed. We paid him $4 million dollars and 5 years later, we still have to use 3 lines to handle errors. THE AUDACITY!
On the other hand, isn't $1.2m per year a bit low for one of the BEST programmers in the world? Not very motivating is it... Oh well. Slaves built America's economy and got paid nothing for it. Now their children suffer and what can they do? Suing a dead slaveholder for theft is like suing Bernie Madoff in jail. You're not going to win the lawsuit, and even if you do his kids won't give the money back… Anyways.
Daniel sees this trolling and says he doesn't want to be associated with me on Github as if he was a major contributor. He has 0 commits. On every public project I have... Look at his profile (at the time of writing). 0 stars. 0 forks. That means no developer impact.
Thomas and I were putting in the — as Daniel would call it — "shitter" work that was literally the fundamental piece of the program called Dasgo which contained the types that would be used to automatically generate the API Wrapper upon a Discord API update; since Discord wouldn't provide a machine readable API. I tried making an IC1 bring up a machine readable API in his retrospective meeting (he brought down production) but there was no hope. The Boomer Discord Developers are stuck in their ways.
The following paragraph references an event that occurred in 2021. Everything eventually becomes relevant. Bear with me for a moment.
Daniel and I once had an argument during our failed startup. This conversation occurred after 500 hours were logged; with 400 hours being logged by me. At some point in our work, Daniel became staunchly against logging his time. He argued that we did not need to track our time to prove we were providing a fair value to the business. I did not agree, so after a few weeks I performed an analysis showing his contribution to the startup which was 1% of the codebase and a shitty outdated diagram that got scrapped when he wasted $7 of mine without any care in the world. That's right. My first failed startup cost me 400 hours and 7 bucko BUCKS. The significance of this is that I knew that he had a low chance of contribution, so him quitting didn't surprise me.
Now don't get me wrong. Daniel is a smart guy. Genius even. However, his inability to work with people is going to be what prevents him from success. Just kidding. Daniel is the type of guy who aces LeetCode without issue. He will have no problem getting by effortlessly. Still much better than an average programmer anyways...
College is increasingly becoming irrelevant to the software development field. Students go 4 years without using Git... I could go on about this for hours but the craziest part about college for me is how "productive" it actually is. We have students whose lifetimes span 22 years to benefit a total of... 0 people. OK maybe that's a bit extreme. They do line the pockets of student debt loaners...
So after all this time spent learning theoretical boolshet, we give them this huge piece of paper and ceremony with it. They feel really special, "smart", and prestigious. Yet fast food workers have provided more value to society than them. It's no wonder narcissism is growing among college students...
This is relevant because while we are doing all of this, I'm — like Daniel — considering dropping out to get a REAL JOB. Or at least that’s what I thought he meant. This consideration was motivated by the countless posts I saw on r/cscareerquestions full of people saying they got jobs, but who had no stars on Github (read: can't code). Then there was the whole Discord Machine Readable API fiasco. Finally, an anecdote from a 7 year old.
People are being paid hundreds of thousands of company coins to sit around all day. Why not do that as well?
I went around asking REAL ENGINEERS what title I should be applying for. Some told me that — because I was able to take a client project from start to finish without help — I would be a Senior Software Engineer. Not to mention, all of the projects and contributions on my resume. Everyone says this except for a guy we will call Tim.
Tim starts the call by saying that he knows everything since he just got his degree. Let's say that Tim is your stereotypical r/programming poster. Knows everything about programming and non-programming topics and looks down on the liberal arts... I ask about the tech stack he is using at his job (which he has worked for a year at), and he "can't tell you [me] what it is". I send him my website and he calls it wack before the page loads. I'm pretty sure it doesn't load that fast.
Tim eventually finishes his rant and says that I'm not a Senior because I have no degree. Keep in mind that this is after the Achievements For Thee (Coming Soon) experience with my parents, so my mind is literally being sadged. Tim ended the conversation with, "y'know what, you might be a better programmer than me but I will not take your advice cause you're not Senior". These are the people I have to deal with for the rest of my career. Is this really an industry controlled by HR and Credential Gatekeepers who see the world in this way?
Tim was right.
I applied to 30 companies for a number of Mid - Senior Level Go Backend roles. To be fair, this is a low amount; nor does it include common companies such as Microsoft, Apple, Netflix, or Quant funds. Some companies never responded or are just responding now. With that being said, here are some notable experiences.
Human interviews are stupid. The more I spend preparing for interviews (while knowing how to code), the more I realize that this is all one abstracted game from the time we hunted in tribes (approx. 10,000 years ago). The reality is that the interviewer can see my Open Source Projects. I know I can do the job (which is why I applied). They know I can do the job. What more do you need to know?
A company is composed of a group of humans. The interviewer is a human who participates in that group. The interviewer understands the role they play and the responsibilities that come with it. They also understand the policies and processes that result in a candidate achieving the job. In certain cases, an interviewer even has the decision-making power to approve or deny a candidate.
I need a job to live. You need a job to live. We all need money to purchase food. Despite this, interviewers still ask stupid questions such as "Why do you want this job?" The interviewer does this to cope with their actions, and to avoid the guilt that comes with the fact that their decisions affect people's lives. If I don't get this job I will starve. Your life continues to be great.
An issue arises when the interviewer begins to cede responsibility for their actions. On one hand, it isn't the interviewer's fault for having a job that receives a large amount of applications. However, it is an interviewer's fault for using trivia and silly questions as a means of selection. People have a right to disagree with the "dance" the interview requires. That's all it is. A bunch of begging for a sense of worth and food. It's no wonder attractive people become the most successful.
So when the topic of names comes up, people get antsy. A psychopath would argue to leave real names out of real stories: It can only hurt your opportunities to include them. It would also increase the chance of the psychopath being outed. A normal person may say that including names isn't professional for insert reason here. That same person complains when unnamed politicians milk their cities for millions throughout the entirety of their careers... It always depends on what side you are on, right?
When someone on the internet tells a sob story that does not include real names, I don't believe them. You can continue to consume your fake stories on the internet. In any case, all of what I'm about to say has only allegedly occurred.
I decided to apply to Discord due to the lack of information about the Discord API in the Discord API Documentation. Unfortunately, the recruiter at Discord rejected me with an automated message. I might have made them mad by writing in their stupid little dynamic form that I — a demographic filling 4% of the software industry — have never experienced a diversity program in Tech. In fact… Why do you think only 4% of the software industry is black? Because the world hates black people.
In reality, I got rejected because “the position fit was not good”. Let me give you a tip. When a company sends an automated rejection with no real information, it means that you can interpret why you were rejected and reapply as necessary. Besides, I already applied to three of their positions. I decided to find the recruiter's personal email and asked why I was rejected (to improve my resume). No response... The next "automated" rejection letter was much nicer though 🙂
After viewing the resumes of a few actual Discord employees, I was likely rejected — despite my “impressive background” — because I was never “employed”; rather contracted. Either that or the fact that I was still in college. Or nepotism. Check out this story from a Discord Employee.
“If I could give one piece of advice to younger-Ian, it would be to view networking less cynically. I always thought of networking as making connections with older, more established professionals - in a way that was almost transactional. In practice, this has almost never been true.
My network is organic. It's who I talk to daily and weekly, outside of a professional capacity. My college friends helped me get a job at Zillow. Online friends helped me get an interview at Discord. Twitter mutuals I shitposted with got me my contract job with the Anime Awards. I've realized that my network isn't something I have to force, and I'm much less cynical for it.”— Ian Mitchell in “Thirty”
Something. Something. If you don't recognize who the <insert trait> in the group is... Maybe it's... why multiple developers are paid over 6 figures and still can't explain how their own API works. What’s more important is that our chances at a Discord Machine Readable API were GONE.
I had a Spotify interview with Matt Mercedes and a shadow. I don’t remember the shadow because she only spoke when I asked her questions. The interview started with an introduction, then we got to the interview. The first domain question was allegedly to explain the difference between “a process and a thread”. This gave me flashbacks to a conversation I had with another engineer over an API Gateway (which may or may not be related to a failed startup). We spoke for hours while the engineer was engaged in — from their perspective — an argument over the vocabulary used to describe some microservices.
Anyways, I totally fucked up the answer to that domain question. I answered the next question well. Then, we got to the LeetCode portion of the interview. In case you are unaware, it’s recommended to ask questions to define the problem BEFORE solving it. I asked the interviewers whether we planned to expand the solution, then implemented one that would account for said expansion. After I was done, Matt decided that we were not going to expand the solution.
I began "optimizing" my O(N) solution to O(1) by reaching for a dequeue, but Matt kept recommending against this data structure in lieu of some other "magical" data structure. I ended up implementing his data structure through fundamentals, but I am unsure if he recognized it. He ended that portion of the interview by stating that "the data structure I [he] was looking for was a circular buffer." This was unfortunate because A CIRCULAR BUFFER IS IMPLEMENTED IN PYTHON WITH A DEQUEUE...
I was rejected for a better candidate (which may be fair). What’s not is the fact that an interviewer can be clueless about their own trivia interview question. We were interviewing for Podcast Monetization (Web APIs), not Computer Science research class. I emailed Matt months later asking for feedback, but he didn’t see it or doesn’t care.
On May 28th, I had a technical interview with Roblox (Karat) but there was a bug in the HTTP request data of the LeetCode question; when we were told to assume there wasn't. This caused me to shet my pants horrendously… Live. On. Video. I technically passed 2 questions but the bug caused my second answer to fail an edge case. Roblox corporate policy requires that you pass two questions. So that's how I got through the second round of a mid-level role.
Over the course of 2 months, I would go through a Behavioral, 4 Onsite, and Bar Raiser rounds: 2 including managers who were considering microservices but didn’t even know what a monorepo was... They wanted to place me at Junior. Fugg it. I needed HR to look past the fact that I didn't have a degree; even though I can solve all their technical problems including a 45 MINUTE BUILD TIME?! I smiled on the outside but laughed very hard in private like a certain religious sect.
The night was June 29th. At this point, all of my interviews were finished. I had even spoken to a manager — on the previous day — who wanted me so badly that he fast tracked me to a decision by the Hiring Committee. I received an email from the recruiter asking for my physical address. This was followed by a call where the recruiter gassed me up: “This is the biggest offer I’ve ever seen for an IC1! Consider me your brother.” Things were getting serious.
On that same night, God sent 2 virgin mormon girls to my doorstep. It was a sign I was headed in the right direction and GODDAMN! One of them was for sure a sinner and I'd sin with her, given the chance of course... I was surprised because I'm pretty sure their religion says black people are demons. I turned them down when I realized they were just with me for the type conversion.
Now, let’s be honest. It’s 2022. Even if the team loved me I knew that there was still a chance I would be fucked over by someone with no stake in the matter. Certain companies hire people based on the decision of people who weren't interviewing. Roblox is one of them. Offers are made on Tuesday, so imagine my surprise when I didn’t receive a call or email… That was until the 6th (of July). It was the recruiter and he had “bad news”.
Basically, despite the team’s best efforts, I was not going to get an offer. This is because — according to the hiring committee — “I wasn’t able to code” since I “took too long in one onsite round while receiving too many hints”.
So what actually happened?
Technical Onsite #2
Let’s start with the second interview which is directly related to the hiring committee’s comments. In this interview, a prompt is given by the interviewer with a shadow. Initially, it was clarified that we would create a single threaded KVS application. I solved this relatively quickly by using a Go map. As a result, this prompt changed scope to a multi-threaded KVS application. So I used a synchronized map. Then, the prompt was extended to implement database transaction functionality. In order to handle the “delete operation” correctly, I had to use a brute force memory solution. The interviewer didn’t like this so we changed scope to database transactions without a brute force memory solution; which involved some weird rules regarding a delete operation. Every time we changed scope, I would ask clarifying questions, which the shadow must have written down as hints. Not to mention, the interview went 30 minutes over schedule.
I would end up implementing what the interviewer wanted right as the “time limit” occurred. The response from the shadow was, “Sorry, but you ran out of time”. So it is possible that I wasn’t even marked as solving the problem.
Technical Onsite #1
In the first interview, I was given 30 minutes to implement a variation of a topological sort problem. At first, I would waste 6 minutes (20% of the interview) re-formatting data in Go then switching back to Python, since the prompt was not auto-filled for Go (but was for Python). So much for using any language… Unfortunately, the initial explanation I gave to the interviewers must have not been clear enough, because one of them recommended against a step (to reformat the given data) which was necessary to perform a topological sort. As a result, I got stuck at minute 22, which was also the moment the interviewers finally understood my solution. I’d spend a minute contemplating whether I should have just implemented a brute force, only to continue the optimal solution. Then, with only 7 minutes left, pressure resulted in a Python syntax error related to a list comprehension. No one in the interview could figure it out.
After a Phone Screen, 2 Technical Rounds, a Behavioral Round, 4 Onsite Rounds, and a Bar Raiser, I had no job. All because I couldn’t solve one LeetCode question. It didn’t matter if I knew how to solve the problems. It didn’t even matter if I could have fixed their 45 minute build time in the time we spent interviewing. All that mattered was solving a trivia-esque question in some unnatural work environment; and dealing with an interviewer who kept changing scope. Some people are going to read this interview summary and say I had a shot and fucked it up. That’s a fair assessment, I guess... I should have done more LeetCode. In any case, Fuck You Roblox Hiring Committee.
I had an interview loop for an SDE II position at Amazon. The interview loop for Amazon consists of an Online Assessment containing two questions, followed by an Onsite Interview. Apparently, acing your OA only requires you to explain your answers to an engineer for an offer. Unfortunately, this option was not available to me due to an issue I encountered with the assessment’s Integrated Development Environment (IDE).
You are given 90 minutes to solve two problems. I would rate these problems as LeetCode mediums with context. The general pattern for each problem was a description of some issue that could theoretically occur at Amazon, but deep down is just a glorified math problem. After spending a bit of time figuring this out, I implemented my solutions in the Go programming language with optimal algorithms. So imagine my surprise when I finished an online assessment at one of the most valuable companies in the world, only to receive an issue: "Time Limit Expired."
After mucking about for a bit, I decided to re-implement my first solution — line-for-line — in Python. This was based upon the assumption that the IDE compiled the program before running it. Compiled languages are faster than interpreted languages, but not if you compile the program every time it’s run. This worked. Or perhaps I was able to gain some edge with an underlying C implementation from Python for that specific program. Nonetheless, I ran out of time before I could translate the second implementation to Python.
The Onsite Interview consisted of 4 Rounds spanning 6 hours. In each interview, you receive ~2 questions regarding Amazon’s Leadership Principles followed by some sort of technical problem. My only significant mistake occurred at the end of the last interview, as I believed I was only given 20 minutes left to solve the Technical Problem. Despite the interviewer allowing me my full time, I was unable to determine how to solve the problem without hints (since we “could only solve it with brute force recursion”). In addition, a few miscommunications led to my implementation taking forever to complete; but alas I finished.
Based on the feedback I was given, I aced the rounds focused on System Design and Leadership Principles. According to the interviewers, I performed decently on 1 of 3 technical problems; which is not what I recalled. I thought that I also passed the Data Structures interview, but Ryan Calme stated otherwise? In that round, I implemented a recursive solution, and recognized an O(1) implementation (if certain conditions were applicable). However, the difference in our evaluations may be due to the fact that he had never used Go.
The Hiring Committee (consisting of the interviewers) was allegedly disputed. On one hand, three of the interviewers would advocate for me while Mohit Mundel would fault me for my poor performance in his technical interview. Apparently, it got to the point where they even looked at my Open Source work. What a crazy thing to do for a Software Engineer evaluation, right? Sarcasm aside, I didn’t get an offer. Mohit — who has been at Amazon for 7 years — had the decision to veto everyone else. He decided to reject me because “I couldn’t do recursion”.
If you’re going to reject me, at least be honest. Tell me, “You couldn’t solve our LeetCode problem” (in the last portion of the last round). Don't tell me I can't do recursion... I can do recursion: Here. Here. Here. Here. I guess they didn’t look at my Open Source work in a thorough manner. Take what you will from that information.
I received a contract — from an actual startup — that paid as much as an offer. Unfortunately, a bad set of instructions (communication) by the co-founders led to an ending of my contract when one co-founder told me to perform an action that led to the other co-founder firing me. To be fair, my role was indirectly related to increasing conversion, but they were not ready for it: I don’t understand how a company can receive VC funding without a single form of monetization, but that startup proves it's possible.
After this entire experience, what advice do I have for prospective programmers? Don't waste your time on Open Source. Don't make the world a better place. Just focus on yourself. Do more LeetCode. We live in a Wagie World.
Wagie World Woes
From May 7th to May 26th, Thomas got caught up in some Wagie World Woes (finals). As a result, he “forgot the project even existed”. During this time I finished up Dasgo, except for a final specification edit. I also created the generator command necessary to generate over 10,000 lines of maintainable code. For more information, read about How Disgo Uses Copygen.
On May 29th, Thomas and I had a talk about the Wagie World: "Thomas, there are currently only two known types of programmers in existence: .1x and 10x…" Fast forward to the end of the week, and I had finished the OAuth2 Flows and HTTP Retries while he had "finished" the WebSocket Code. Progress was being made.
An unemployed college graduate named Josh Dawe needed help. I gave ‘em a job alright. After a night of mentoring, Josh finished up Dasgo by implementing the final specification on June 6th. After that, I tasked him with OAuth2 Unit Tests. That's all he needed (along with ATS Resume advice) to be successful. “He got the job.”
I would spend another week "finishing" WebSocket Code while Thomas got paid $50 an hour to watch videos related to orientation all day at his internship. Meanwhile, Daniel was also getting paid to watch videos all day at an internship… These interns get paid $XX to watch videos the whole week; and paid more than the creators who made the videos in the first place. Meanwhile, in Africa...
On June 8th, Dasgo was merged into the official Discord API Documentation.
We had originally planned to release Disgo in the week of June 20th. However, we still needed more tests along with a working rate limit implementation. I was halfway into implementing rate limit functionality before I realized that the Discord employee who created the original PR for the rate limit documentation had no idea how Discord implemented their rate limits. This meant that I would have to do experiments over and over until I finally got it right. While all of this was happening, people kept missing scheduled meetings.
Progress slowed to a halt until July 5th. All my time was being wasted to determine the rate limit implementation. Josh was dealing with his job offer. Thomas was bogged down by his internship. This led me to engage in a long period of thought; where I would stare into the void for hours in an attempt to assess the situation. "Fuck. We're blocked."
A deep sense of shame overtook my body: Were we really going to go 4 months for nothing in return? When people don't really understand the importance of these projects (enough to be motivated), what's the point? Then, I had an epiphany. You can imagine an equivalent to Newton’s apple experience, but I’m Newton and the apple is a lone Amazon Recruiter marching their way into my inbox. At that very moment, there was only a single thought to be had.
"What would Bezos do?"
I told the wagies that I wouldn't give them future job referrals unless we finished the project in 14 days. It worked, sort-of.
From July 13th to July 14th, I refactored websockets. I fixed the tests of websockets. I fixed the heartbeat functionality of websockets. I fixed the disconnect method mutex semantics. I added a reconnect method to websockets. I sped the tests of websockets from 45s to 6s by using a jitter interval trick. I fixed the data races of websockets. I added commands to websockets. I updated the documentation for websockets. I added CI for websockets. I merged websockets.
On July 15th, my ass got blown up by a Mexican restaurant.
After all of his hard work on Dasgo, Thomas was exhausted. "I hate this project. Every day I come home from work, and then I do more work. When I work on Disgo, it is my life. Once we finish this project on July 21st, I'll never work on it again." You know what else gets this attitude? School projects. I decided to up the complexity of assignments on Thomas so he'd take more ownership.
A Full Coverage Integration Test
I had this idea for an Integration Test that would grant us full coverage of the Discord API. One that would make Disgo the number one API in terms of reliability. For the unaware, an integration test is a test that interacts with the real-world environment. Remember when HBO Max sent a test email to all of their subscribers? Yeah. That’s an integration test gone awry. In any case, an integration test is used to ensure that your code provides the functionality it promises.
Thanks to Dasgo, we already had every feature, event, and route (176+) in an automated pipeline (via Copygen). All we had to do was call these routes (and respond to these events) in an optimal manner; to save time on CI. Once Thomas understood the task, I gave him full jurisdiction to find a solution. Unfortunately, he got blocked immediately.
I drafted up a plan fairly quickly since we were so close to the official release and I wanted to save time. The plan included a 4-step process to find the optimal request order for all 176 Discord API Endpoints by using data input and a topological sort. That’s right. For the first time in my career, we were using something I already did on LeetCode.
There was a problem, though. Despite my explanation on the issue we were solving, the task at hand, providing the theory to the solution, AND the public commented code (I created), Thomas could not figure out how to implement a solution within 3 hours. An entire 3 hour call was wasted on ??? I spent the last 20 minutes finishing the task up for him (with an explanation) while he watched. Now Thomas is a hard worker, but THIS AIN’T IT! I realized that something was extremely wrong, but I didn't understand it until later.
Josh spent time with his girlfriend since he had to move due to his job. Well, that's definitely not what happened. Josh had his first programmer moment and faced impostor syndrome upon being assigned examples. It was causing way too much stress in his life; in addition to the move his job required. I decided to help him out and cut him from the team.
From July 16th to July 19th, I'd refactor WebSockets to provide better stability to the connect, disconnect, and reconnect functionality. I would identify and fix all data race issues. I would also add Gateway Commands on a call so that Thomas could learn how to use Copygen. And I'll admit. My mental concurrency models needed work. These tasks upgraded them.
With the major WebSocket features out of the way, all I had left was to merge Rate limits. Thomas had to put the test together, and used Copygen to save himself from writing 2000 Lines of Code. For the first time, Thomas was becoming a 10x. We had planned to release the project on the next day (July 21st), but we faced an oversight regarding the tests finalization. After this realization, we made yet another discovery on Discord's entirely non-uniform non-standard rate limit per insert thing that requires optimization.
This comment by Discord sums up the Developer Experience entirely: #2190-816363129. The documentation tells us to use a token bucket algorithm for rate limit handling for EVERY ROUTE. There are 176 routes which would imply 176 different token bucket rate limits. In practice, certain routes don't have rate limits; instead using the Global Rate Limit which is actually a fixed window rate limit. API developers are told to rely on the rate limit headers Discord gives, but then Discord admits that they can always be inaccurate…
So imagine getting through all of that only to realize that Discord also has these magical "per-resource" rate limits that are explained in the most confusing language you have ever seen. "Emojis don't follow conventional rate limits and top-level resources have their own rate limits." What the fuck does this mean??? FUCK! Rapptz was right… I looked for inspiration from the community (DiscordGo and other wrappers), but they don't even handle it correctly (after 7 years).
I would eventually figure out the full implementation around the release of Disgo Beta. However, I was not going to create an implementation until the Full Coverage Integration Test was complete; since it would allow me to confirm my findings. Once this occurred, Disgo would be the only API Wrapper featuring a complete and correct rate limit implementation for the Discord API.
The Beta Release
Disgo was not supposed to have a beta release. In fact, everything listed in #11 — which is everything except sharding, caching, and voice features — should have been completed after 5 months (March 1 - July 26) of working on the project. I changed my mind for two reasons. First, it was around this time that I had the onsite at Amazon, so placing the project in a releasable state would be beneficial for me. Second, Thomas decided that this was the last day he would work on the project “for a few months" so he could relax until school started. Regardless, it became clear that we wouldn’t have finished even if Thomas continued to work.
Thomas and I were taught the basics by the same teachers, but somehow he became a spray and pray programmer. Remember when I realized that "something was extremely wrong"? This was it. Why couldn't Thomas put together the modified topological sort in 3 hours with everything he needed in front of him? It was because he viewed code as the ends rather than the means. A spray and pray programmer does not think about the lines they are writing. They take what they are told to do and hope for the best. This results in copied examples and hoping the code just works, rather than looking at each line as an action in a series of steps.
When this type of thinking permeates into a lifestyle, you get a modern wagie. Doing something because everyone else does it, with an illusion of an end goal in mind. It's impossible to motivate someone with no real end goal. This is why Thomas was unable to contribute much when the implementation wasn't spelled out for him. There is no critical thinking or individual actions when you spray and pray; only vague plans manifested by others (i.e College). Sometimes these plans work for you, and sometimes they don’t.
Thomas and I would work together to eventually fix this issue (of spray and pray programming). However, at that point in the project, it was clear that he was not going to finish his task (even if I gave him months to do so). He himself admitted that the achievement of Disgo wouldn’t be something he was able to comprehend. So I can understand why the motivation wasn't there to finish: From his perspective, we were doing work for the sake of it with no end in sight. Thomas is a great person, but it didn’t change the fact that the project would be delayed and I was — yet again — stuck with his workload.
Disgo v0.10.0 was released on July 26th, 2022.
A Waste of Time
At the start of the year, I was on my ass looking for a way to become a normal person. No matter which way I looked, I realized that money was the only thing holding me back. I have potential in many aspects of my life, but need the freedom to execute those aspects. While I may have improved my skills in these aspects in the last 8 months, I am still without enough money. I am still held back; maintaining more potential in these aspects. In a way, I am in the same place as I was at the start of the year. What a waste of time.
At least I’m not in hell. I just need to stop making articles such as these.
On the other hand, Discord’s API showed me how much of this industry is truly a grift. It boggles my mind how one can create a system with the purpose of others using it, only to make it impossible for others to use. I shouldn’t have to waste 2 months (and more) to adhere to your rate limit standards. At the very least, provide a coded example for the consumer (developer). Let’s not forget that Discord’s API Documentation is mainly built off the backs of bored high school students. It’s things like this that showcase an inefficiency the industry has yet to exploit. I canceled my Nitro subscription.
Despite these setbacks, we were still able to create a usable solution. Thomas — who started out as a noob — even contributed a few KLOCs. This guidance is why I should be classified as a Senior Engineer, but a lack of credentials causes jobs to place me at a Junior or Mid-Level role. It has become obvious that some level of spray and pray is required when the world uses it to evaluate everything.
At the end of day, Daniel got into the University of Texas (following his internship). Thomas made big bucks at his internship. Josh relocated to his job. Everyone was making money, except me. Well… In the eyes of Capitalism, they are better programmers than me. I can't argue with that. It's time for me to waste another month on LeetCode.
What do I have to say about this project? I learned a lot. Definitely accelerated my programming career. However, it is not that fulfilling. In hindsight, there is no reward in Open Source. I look up at the stars at night and wonder if I made the wrong choices in my life... Oh. Look. Copygen hit 150.
I once gave a prostitute on the internet advice on how to code; since she was looking for a career shift. Sent the roadmap and resources and everything... However, I feel bad now because pursuing software development might just increase her suffering. I was at a hairdresser when it dawned on me that most people's lives revolve around people; not their career. They go to work, speak with family, and come home to a community. Work is just a means to an end.
Accountants don't interview other accountants by giving out LeetCel questions or attempting to downplay each other's queries. They just ask who your father is. This is in stark contrast to Uber's Leo Horie, who — upon reading some fake story I made up about placing a GPL license in a take-home interview assignment — went out of his way to state how wrong it was, then downplay the complexity of the problem Copygen solves since "it took him [me] 2 weeks". Gave me a chuckle, ngl.
Alright, so now for the real reason you clicked on this post. How did 3 people create a project that took 150 people 7 years in 6 months? Let's do the math: 3 people * 6 months = 18 for a feature-complete State of the Art API Wrapper. 150 people * 84 months = 12600 for an unlinted, poorly maintained Garbage API Wrapper. 1 person mentoring 2 people means those people grant a handicap of ½ or
.5. This results in the following equation:
12600/(18 * .5) = 1400 which makes me a 1000x programmer. So that's how.