Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lessons/275/bun-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"typescript": "^5"
},
"scripts": {
"build": "bun build --compile --minify --sourcemap ./src/app.ts --outfile bun-app"
"build": "bun build --compile --minify --sourcemap --sql-preconnect ./src/app.ts --outfile bun-app"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--sql-preconnect is for runtime not bun build, though I think we could do a --compile-exec-argv=--sql-preconnect type thing

But with how its set via config.yaml and not env vars, I can't see any way this is usable here

Copy link
Copy Markdown
Contributor Author

@solmanter solmanter Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your are right, that should on runtime

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like default behavior anyway, when you deploy an app, it creates all those connections immediately. The more interesting question is why, by the end of the test, it drops the number of connections.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is interesting to me, i can't find the reason in my tests and benchmarks. It always stayed the same

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this pre connect does is start the connection before javascript code. Which means in theory faster... but as its not set in DATABASE_URL, this flag can't be used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is incorrect for this build and it's not important because bun simply ignores this flag. Also, database connections somehow decreased during the bun benchmark. And it done before this update. That's the real problem.

},
"dependencies": {
"js-yaml": "^4.1.1"
Expand Down
78 changes: 31 additions & 47 deletions lessons/275/bun-app/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,51 @@
import config from "./config.ts";
import { save } from "./users.ts";
import type { User } from "./types.ts";
import type { Config } from "./config.ts";


const server = Bun.serve({
// Timeout in seconds to match Node.js
idleTimeout: 60,
development: false,
reusePort: true,
port: (config as Config).appPort,
port: config.appPort,
async fetch(req: Request): Promise<Response> {
const path = new URL(req.url).pathname;
if (path === "/healthz") return new Response("OK");

if (req.method === "GET" && path === "/api/users") {
const users: User[] = [
{
id: 1,
name: "David D. Patton",
address: "1670 Stiles Street",
phone: "412-578-3857",
image: `user.png`,
},
{
id: 2,
name: "Gary E. Eaton",
address: "828 Collins Avenue",
phone: "614-866-1660",
image: `user.png`,
},
{
id: 3,
name: "John J. Fox",
address: "1895 Columbia Mine Road",
phone: "304-505-3622",
image: `user.png`,
},
];
return Response.json(users);
}
if (path === "/healthz") return new Response("OK", { status: 200 });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could easily be a Bun.serve routes property instead of in fetch() to be really static. The dynamic functions also too, because new URL is really expensive in JS and is doing a lot more than you need here

https://bun.com/docs/runtime/http/routing

For example code
const server = Bun.serve({
  routes: {
    "/healthz": new Response("OK", { status: 200 }),
    "/api/users": {
      GET: async request => {
        const users: User[] = [
          { id: 1, name: "David D. Patton", address: "1670 Stiles Street", phone: "412-578-3857", image: `user.png`, },
          { id: 2, name: "Gary E. Eaton", address: "828 Collins Avenue", phone: "614-866-1660", image: `user.png`, },
          { id: 3, name: "John J. Fox", address: "1895 Columbia Mine Road", phone: "304-505-3622", image: `user.png`, },
        ];
        return Response.json(users);
      },
      // or event simpler, but it feels like possibly cheating:
      GET: Response.json([
        { id: 1, name: "David D. Patton", address: "1670 Stiles Street", phone: "412-578-3857", image: `user.png`, },
        { id: 2, name: "Gary E. Eaton", address: "828 Collins Avenue", phone: "614-866-1660", image: `user.png`, },
        { id: 3, name: "John J. Fox", address: "1895 Columbia Mine Road", phone: "304-505-3622", image: `user.png`, },
      ] satisfies User[]),

      POST: async request => {
        const incomingUser = await request.json() as User;
        const datetime = new Date();

        const user: User = {
          name: incomingUser.name,
          address: incomingUser.address,
          phone: incomingUser.phone,
          image: `user-bun-${datetime.getTime()}.png`,
          createdAt: datetime,
          updatedAt: datetime,
        };

        try {
          const record = await save(user);
          user.id = record[0].id;
          return Response.json(user, { status: 201 });
        } catch (error: unknown) {
          return Response.json({ message: (error as Error).message }, { status: 400 });
        }
      },
    },
    "/*": new Response("Resource not found", { status: 404 }),
  },
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static routing is indeed faster, but we keep it around because we aim to simulate real-world scenarios as closely as possible. and similar code structure like go

Copy link
Copy Markdown

@RiskyMH RiskyMH Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For similar, we should at least use routes then (at very least don't use URL class)... but using actual static is pretty real world imo (its not like its a hidden feature of bun)

If your talking about the GET request for users, yeah that imo should be DB anyway

if (path === "/api/users") {
if (req.method === "GET") {
const users: User[] = [
{ id: 1, name: "David D. Patton", address: "1670 Stiles Street", phone: "412-578-3857", image: `user.png`, },
{ id: 2, name: "Gary E. Eaton", address: "828 Collins Avenue", phone: "614-866-1660", image: `user.png`, },
{ id: 3, name: "John J. Fox", address: "1895 Columbia Mine Road", phone: "304-505-3622", image: `user.png`, },
Comment thread
solmanter marked this conversation as resolved.
];
return Response.json(users);
}

if (req.method === "POST" && path === "/api/users") {
const incomingUser: any = await req.json();
const datetime = new Date();
const key = `user-bun-${datetime.getTime()}.png`;
const user: User = {
...incomingUser,
createdAt: datetime,
updatedAt: datetime,
image: key,
};
if (req.method === "POST") {
const incomingUser = await req.json() as User;
const now = Date.now();
const datetime = new Date(now);
Comment thread
solmanter marked this conversation as resolved.

return save(user)
.then((record: [{ id: number }]) => {
const user: User = {
name: incomingUser.name,
address: incomingUser.address,
phone: incomingUser.phone,
image: `user-bun-${now}.png`,
createdAt: datetime,
updatedAt: datetime,
};

try {
const record = await save(user);
user.id = record[0].id;
return Response.json(user, { status: 201 });
})
.catch((error: Error) => {
console.error(error);
return Response.json({ message: error.message }, { status: 400 });
});
} catch (error: unknown) {
return Response.json({ message: (error as Error).message }, { status: 400 });
}
}
}

return new Response("Resource not found", { status: 404 });
},
});
Expand Down
4 changes: 2 additions & 2 deletions lessons/275/bun-app/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFileSync } from "fs";
import { load } from "js-yaml";
import type { Config } from "./types.ts";

const config: Config = load(readFileSync("config.yaml", "utf8")) as Config;
const config: Config = load(await Bun.file("config.yaml").text()) as Config;

export type { Config } from './types.ts';
export default config;
Comment thread
solmanter marked this conversation as resolved.
10 changes: 7 additions & 3 deletions lessons/275/bun-app/src/db.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import config from "./config.ts";
import { SQL } from "bun";
import type { Config } from "./types.ts";

const { db } = config;

const sql = new SQL({
url: `postgres://${(config as Config).db.user}:${(config as Config).db.password}@${(config as Config).db.host}:5432/${(config as Config).db.database}`,
max: (config as Config).db.maxConnections,
url: `postgresql://${db.user}:${db.password}@${db.host}:5432/${db.database}`,
Comment thread
solmanter marked this conversation as resolved.
max: db.maxConnections,
idleTimeout: 60,
connectionTimeout: 30,
maxLifetime: 1800
});

export default sql;
10 changes: 2 additions & 8 deletions lessons/275/bun-app/src/users.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import sql from "./db.ts";
import type { User } from "./types.ts";

export async function save({
name,
address,
phone,
image,
createdAt,
updatedAt,
}: User): Promise<any> {
export function save(user: User): Promise<[{ id: number }]> {
const { name, address, phone, image, createdAt, updatedAt } = user;
return sql`INSERT INTO bun_app (name, address, phone, image, created_at, updated_at) VALUES (${name}, ${address}, ${phone}, ${image}, ${createdAt}, ${updatedAt}) RETURNING id;`;
}