-
Notifications
You must be signed in to change notification settings - Fork 2
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
Auto-approve trippees #91
base: main
Are you sure you want to change the base?
Conversation
Before rendering the various trip cards
src/routes/trip-members.js
Outdated
export function autoApprove (tripId) { | ||
return (db) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't think of any reason why this function should return a function instead of just being:
export function autoApprove(db, tripId)
Am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was an overkill here, but the idea is that tripId
and db
are very different kinds of input. They're different in where those values are available. So tripId
is readily available in any business logic, but db
is provided only through the Express middleware. The idea is a function that only takes tripId
may be useful in other parts of the stack that doesn't necessarily have access to db
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know what you're thinking, but this function in particular is never going to work that way, because as autoApprove
, it's always going to need DB access to do its job.
ALTER TABLE trip_members | ||
ADD COLUMN added_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think we need this—the order they're in the table based on the ROWID
is going to be the order that they were added at. To create new ROWID
s, SQLite basically does SELECT max(id) + 1
.
trip_members
does not have an explicit INTEGER PRIMARY KEY
, but it still has a hidden one, essentially, because INTEGER PRIMARY KEY
is just an alias for ROWID, which SQLite will always include unless you explicitly ask it not to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case trip_members
table has a PRIMARY KEY (trip, user)
and so it ends up sorting by the trip ID then user ID, instead of order added. It definitely would've been nice to just rely on insertion order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally you would be right, but SQLite works a little differently in this regard (namely, you always have ROWID
unless you explicitly say WITHOUT ROWID
). See: https://www.sqlite.org/rowidtable.html
Also add: "Resolves: #46" at the end of the description so that it links to that issue and auto-resolves it when the PR gets merged. |
src/routes/trip-members.js
Outdated
export function autoApprove (tripId) { | ||
return (db) => { | ||
let moreToApprove = true | ||
while (moreToApprove) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a substantial comment that got lost somehow, sorry to add this after.
A while loop is not the way to go here, for two reasons:
- If there's any possibility of the while loop not terminating, it will crash the program by blocking the event loop. The other two while loops in this code have much simpler terminating conditions, and writing this makes me think I should re-evaluate them, honestly.
- Generally speaking, it is much simpler (and more efficient) to let SQL handle operations over multiple entries, in this case meaning "all the people who are pending admittance". Think functionally (operations over arrays) not procedurally (loops).
A better way to do it is the following:
- If the time is less than 24 hours from now, return
- Get the total number of members currently in the trip
- Get the number of auto approved members
- Let X be
auto_approved_members - total_members
. If X >= 0, get the pending trip members, limit X, ordered byROWID
- Admit them to the trip
- Send them emails
No loops required (though a map
or forEach
is the simplest way to do the emails). I would do (4) and (5) as virtually identical statements, with (5) as an update; this is much easier than trying to do an array input to SQL. (2) and (3) can be combined into one statement pretty easily, if you want to test your SQL.
@@ -32,8 +33,20 @@ export function sendToWaitlist (req, res) { | |||
const owner = req.db.get('SELECT owner FROM trips WHERE id = ?', tripId).owner | |||
if (userId === owner) return res.sendStatus(400) | |||
|
|||
req.db.run('UPDATE trip_members SET pending = 1 WHERE trip = ? and user = ?', tripId, userId) | |||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Total style nitpick, but I think you're over-explaining yourself here. Consider:
// Remove then re-add member so that they're at the back of the auto-approval queue
req.db.run('DELETE FROM trip_members WHERE trip = ? and user = ?', tripId, userId)
req.db.run('INSERT INTO trip_members (trip, user, leader, pending) VALUES (?, ?, ?, ?)', tripId, userId, 0, 1)
autoApprove(tripId)(req.db)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I think about it, the UX is going to be pretty bad here if you're sending people to the waitlist but the auto-approval is on and it adds them right back. What do you think is the right solution to that? I think maybe we should disable "send to waitlist" entirely if the auto-approval is on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have thought about this more and let's do it this way: can't send anyone to the waitlist if you're auto-approving. Makes everything cleaner, less likely to have unexpected behavior.
If the trip already left, show attendance record
Seed trip 5 demonstrates auto-approve feature
013451b
to
d42cb94
Compare
To test, reseed the database, then login as
userId = 1
and opentripId = 5
, called "POCO x NAD Sugaring Trip!🍁🥞".Resolves #46