I almost can't bring myself to type the line
Streamed
Fixed comment reply bugs in Lobsters by simplifying JavaScript selectors and DOM manipulation PR #1493. Discussed coupling between JavaScript and HTML templates, and why testing is hard with import maps. Story about working myself out of a support engineering job alongside a net negative producing programmer.
scratch
topics
comments!
replying from /comments, no form
replying /replies, no save!?
previewing
need an infra fix
net negative producing programmer story
https://wiki.c2.com/?NetNegativeProducingProgrammer
app js line 298: qS(form, 'textarea').value = "";
so that posting a top-level reply and reloading doesn't show your already-posted comment as if it hadn't been posted
but this really doesn't feel safe
title
I have such trauma around deleting user input that I almost can't bring myself to type the line
post-stream
Transcripts are generated with whisperx, so they mistranscribe basically every username and technical term. They're OK but not great, advice appreciated.
Recording
05:00Took me an extra second to grab a glass of water. So let's start.
...14I'm Peter, and this is the Lobster's Office Hours stream, and I should show you that this is Lobster's.
So if you have any questions about
how the site works, how the code base works, want to run queries against the production database.
We can do that.
I usually stream for about three hours.
I may go a little short today.
We'll see.
Because I burned a whole lot of time over the weekend writing a big long post on the UK Online Safety Act, which is a topic that has come up a lot on stream.
pushcx https://lobste.rs/s/ukosa1/uk_u…
and figuring out what the heck it means for the site and how to handle it and write responsibly about it has been a big topic so yeah if folks have questions about that we can jump into it because i ended up posting this big comment what sunday morning my time which was
Trying to do the time zone math in my head, but like 10 hours before the online safety act, it's big censorship provisions took effect.
So to flip it around the other way, they took effect almost 24 hours ago.
And my comment was posted 27 hours ago.
Yeah, that sounds about right.
So this is long.
I think it was like 3,400 words, but that was, I don't think I even word checked the final draft.
So maybe it got up to like 3,500 or so by the end.
But it is a big explanation of all of the stuff that we've figured out in the last couple of months.
And the high bit of it, the dominant factor of this one is
I removed the pending geo block because the risks seem lower, both because there's no reason to think that the UK has a mechanism to enforce this, has a legal theory for why they should be able to enforce this internationally, even if defending against that kind of overreach would be ruinously expensive and distracting.
And then, even if the UK does get to make laws for the entire world... Yeah, I'm going to skip the snarky historical asides, but I presume folks are familiar with the British Empire.
Even if the law could be applied...
It doesn't apply because reading the law, it has a couple of carve outs and lobsters falls into several of them.
And then, oh, my little numbers got all messed up.
See Markdown does the wrong thing once in a while.
I am not going to fix that.
And the big one is that lobsters is an email service.
Lobsters is.
That is, that quote got fucked up.
It's hard to edit these things.
I was just writing like, I did almost all of this writing on an iPad and iPads are terrible for text editing and it didn't help that I had a whole bunch of lag in the system too.
A little painful.
So that's my ramble there.
twitchtd hi, thanks for your work on osa research
Frici A massive block of text shows how much of a pain markdown can be sometimes... I like it but also oh boy sometimes.
And then if folks don't have any kind of questions, I tend to work on the code base.
And that's reviewing pull requests or making bug fixes, just trying to get stuff working or improved.
So there is a small thing I am peeking at off screen.
Frici Also Greetings pushcx , twitchtd
because I touched DNS and if you touch DNS you can never ever trust that it's working for like
four hours.
Ah, hey, Fritchie.
Yeah.
Frici you can't trust its working if you don't touch it either LUL
Yeah, I also like Markaria, but...
I'm sorry.
Markdown.
Thinking of a different topic.
Alright.
10:38espartapalma Hi y'all
Frici Hey espartapalma 👋
All right, so... Yeah, Fruity, that is the voice of experience I am hearing when you say that, that you can't trust DNS even when you don't touch it.
Yeah, that's... We've had a couple of DNS-related problems on lobsters before.
So this is me trying to avoid problems in the future, but then...
Doing nothing is also a problem.
Doing something is a problem.
You pick your risks.
And hey, he's Bart Palmer.
Welcome back.
So I'm going to go take a look at the pull requests and issues because nobody's starting off with a office hours question.
But if folks have them, you can drop them in any time.
And this one, I talked a little in the chat room about this.
11:47twitchtd hey @Frici
I wonder, Shamless, if you're here, I see that you opened a pull request about this.
I wanted to review and hopefully merge it and then think about what it means to, oh, hey, Twitch TD, to improve the infrastructure around comments because this is clearly just not working reliably.
12:32chamlis_ hi all! I'm around, yep
So I just wanted to start there.
Oh, hey, Shamless.
Great.
So I saw the main thing that's happened is you opened this pull request.
...57Editing it while nested. I didn't come at top level.
13:05When you say editing a comment at top level on this page, you're talking about if you use the text area at the top of the page to create a response and then other threads filter in, your comment is still considered top level. Or in other words, you're saying depth is zero because it has no parent. It's this hoisted to the top on a refresh that's throwing me. Let's take a look at the code.
...46chamlis_ ahh right, obviously the page doesn't nest, but the reply will show up as nested until you refresh the page
Yeah, so this is the kind of...
...56Okay, I think I follow. This is the kind of edit that scares me because it probably works. And I say probably works because I am playing a computer in my head and I can recognize the differences in the markup, but we don't have anything reliable. We just have all of these selectors coupling the JavaScript to the rendered templates, and we don't have a We don't have a test of that JavaScript, and we don't have a test of that markup. And so when comments get reused in different places under different markups, we get all of these really buggy events. And it's not helped by the style of the code base of writing deeply nested selectors. That's mostly on the CSS style side. I've been cleaning them up on the JavaScript side, but we still have a few. So it's wrapping a div and then adding a class. The fact that comments index.
15:30valeriodima hi, im a long time lurker, does anyone has an invite to spare?
What does this render?
...36Yeah, see, this is the same markup and probably needs the same fix.
Hey, Valeria, Dima.
pushcx https://lobste.rs/chat
If you look at...
chamlis_ ahh, true
This page chat lobsters has a chat room, you can drop by and folks there will.
valeriodima ty love the community
Probably there's somewhere yeah there's a whole paragraph here about getting an invite so.
Where you can fix some bugs I definitely send people invites when they fix bugs someone just did that the other day actually that's worth showing off a little there's just this pull request that I merged over the weekend for.
Where was it?
16:32Wasn't there?
Oh, no, it wasn't here.
It was on Mastodon, actually.
Someone spotted a bug in my commit and I edited to fix it.
And then I sent him an invite.
pushcx https://github.com/lobsters/lob…
So anyways, the other real easy way to get it
invite is to fix a bug.
And I introduce bugs for this all the time.
That's our primary invite mechanism, right?
Feels like it with this commenting.
So yeah, Shamless, looking at the replies template, you know, you can see it's a copy and paste from what you just edited.
And so this probably has the exact same bug.
And we're kind of
17:28problem here is the coupling between the templates and the javascript and we're kind of alternating fixes in a way that's scary to me because we're going back and forth like oh well let's just fix the javascript and then some bugs creep in and then we're like oh let's just fix the template and then some bugs creep in and we're like oh let's just fix the javascript
And so when I find myself alternating like that, the core problem is that we're violating DRY.
And these two things are coupled, but there is no technical mechanism that forces them to move in sync.
And one solution is to just play whack-a-mole with the bugs until you get rid of all of them.
That's not great.
That's what we're doing now and An obvious next step is okay well let's add a testing system to it, and then, if we test every instance of using the javascript on every template that includes the comments.
chamlis_ are we looking for an abstract CommentTree type then, that stories can coerce into
We have some feeling that it didn't break.
And that's better ish but it's a big investment of time.
yeah and then a better fix is how do we make it not possible for the selectors and the template to slip out of sync and that's kind of the big problem of javascript from 2007 to 2000 what year did react come out 2013 and then react's answer was well get rid of the template
and move that into JavaScript.
And then you have one thing that you edit, and it's all in one place.
And I sure am not changing this into a single page app.
So that's right out the window.
alex4tmm cant hotwire fix the problematic JS ?
So I think what I want to do is, because this is such a bad bug.
core functionality breaking hotwire sort of could but it's it's digging a fence hole with a bulldozer it's such a big tool and
chamlis_ I can grep to try and find the copy-pastes and amend that commit if you'd like
I'm reluctant to invest more in the Rails frontend tools when I can't debug them, right?
Yeah, Shamless, if you wanna do that, because otherwise that's just what I'm gonna do on this stream here for expediency's sake.
So there's, we ran into this maybe two streams ago, and Alex, if you're familiar with,
hotwire, or even just the new import map features, I ran into a limitation of it where if you look in the debugger, you can see our JavaScript.
And we have functions like, okay, so we have this function CRSF token.
And it's coupled to the DOM and it just says, go find the CSRF token in the source and return it.
Great.
Let's run that function, right?
I want to know what that is.
And we get
uncaught reference errors because import map bundles the code up in a javascript module and now i can't get at it and test anything and so it is absolutely a non-starter to me right now to add hotwire or turbo or any other kind of front-end tooling
because even the debugger is just broken right now.
And I'm really frustrated by this limitation because it takes an incredibly powerful tool out of my toolbox.
God, debugging before the JavaScript console was so awful.
I don't even have words to describe how painful that was.
It was the worst printf debugging I've done that wasn't related to hardware design.
So Hotwire addresses this problem and could be a tool.
And it could be very close to what I'm saying about the problem is that the JavaScript and the HTML can slip out of sync.
But I have no way to tinker with the Hotwire.
I can't watch what it does.
I can't use the JavaScript console.
And as long as I'm wearing mittens on the front end right now, I don't want more front end fixes.
23:02Yeah. I was chewing on this because I saw the issue on, I think it was reported on Saturday. And if I wasn't dealing with so much OSA BS... I would have fixed it on Saturday, but...
...26But it gave me a minute to think about, like, what are we doing? Because we're just playing whack-a-mole with this.
24:04So I think the immediate fix is to give Shameless a minute to finish that search for duplicates and then merge this PR and deploy it live on stream. And then the real fix is to do my own version of that search and extract everything to a reusable template instead of copying and pasting stuff around because it should not be possible for these things to slip out of sync like this and then we're down to well if there's only one markup and the javascript matches that if i test any page you know and i'm saying manually exercise any page, then I have exercised them all, hopefully, which is fine for our needs, at least until I break everything by replacing ERB string soup with some kind of component system. I guess that makes sense. That's a reasonable strategy. All right.
25:34So let's look at this.
And it's going to be, especially any time we see
render call to comments comment.
So Shameless, I'm starting to chase after you.
chamlis_ sorry, there were more than I anticipated
chamlis_ plus I forgot an emacs command
I hope you can hear me, but if you have an ETA, that'd be real handy.
26:21I was worried about that, that there would be... Oh, Emacs.
...35chamlis_ just force-pushed, I'll be checking the diff at the same time as you probably
hmm so as i'm looking at these yeah yeah these are the hassle oh my pull request just jumped in my vision and the refresh button appeared let's look so you found
The one on user threads, the one on flagged comments.
27:17Yeah.
...23chamlis_ oh it came through by magic
This diff looks reasonable.
...35chamlis_ huh, neat
not not magic github has some kind of you know like comments and change comments will appear on the pull request or issue as your if you have it open and you know pull request changes from open to closed at live updates so when you pushed it added a button here that said refresh to get the new diff and i don't know if that's because you force pushed and there would have been a more
relaxed version for adding files or adding diffs, but that's fine.
That's neither here nor there.
All right.
28:35You know, the fact that there's six of these, you got a typo here, Shamless, on line four of flagged comments. You're missing the closing angle bracket.
29:03The fact that there's six of these. Thanks, you got it. The fact that there's six or seven of these makes me wonder if we should be editing the other direction so that none of them have it. What is this doing?
...35Oh, it's in this new... Why does this require this ID?
chamlis_ good question
I don't know.
30:03I think it might be echoing a selector from the CSS, which are all a little longer than they should be.
...32So changed in this diff. So Shamless, it is a good question for you? No, because it was already like this before. And then you moved it up. Okay, so you didn't originate the code. Let's step back through the blame. I really wish Git had a less weighted term for that. I do like that there's the anodyne. Annotate.
31:13So then that came from this diff for delete the span prayer comment as children. Right. And that moved this down.
...39yeah i don't and this was the thing that broke it so maybe we just want to pull this story comments parent selector out do we have anything that uses dot comments
32:29alex4tmm is <%= render partial: @above if @above %> correct? or shoulst it be <%= render partial: @above if @above.present? %> as far as i know first option can introduce some unwanted behaviour
Alright.
Alex, the difference is whether above needs to differentiate between nil and false.
And it doesn't.
That's a couple of
Things.
So no, that doesn't change anything for that code.
Cat, could you not play on my, thank you.
33:29I really want us to search for any class of comments I know i'm going to get a whole bunch of extra fixes extra hits. But the way markdown works I can't really filter that so we have flagged comments.
34:14It's just the kitchen sink because comment has got object.
...24Let's cut it down. Now I'm worried I'm going to miss some, but really?
...57Yeah, Shameless, I actually think we want to go the other direction here of just fixing the selector, which is...
chamlis_ I'm inclined to agree, yeah
I know it's exactly the thing I said I don't want to do, but I also don't want to ping pong between the CSS, the JS, and the HTML.
Yeah.
So your pull request...
kind of proves the reason we shouldn't merge your pull request, because it's kind of a shotgun edit.
Oh yeah, we got underscore threads.
Okay, yeah, you did get that in your PR.
No, you didn't get that in your PR actually.
then there's user threads yeah all right let's there's one other thing i want to check all right at least story comments doesn't have any css associated with it because if it did then it's like all right i'm breaking all those pages because
We have very fiddly old school CSS.
36:49All right, so if I did just that, let's look at this.
37:08chamlis_ is that fallback query deterministic now it doesn't require being a direct child of #comments_subtree?
Localhost is doing that dumb cache thing.
...19chamlis_ #story_comments, soryy
chamlis_ yeah
You're saying the fallback, the or on 295?
...34It should be, because comments as a class, well,
I was about to open my mouth and say shouldn't appear multiple times on a page and then I looked down at like literally on my screen, it appears multiple times on the page.
Oh, that's because there's a couple branches through for whether it has replies or not.
Let's look at this one.
chamlis_ I think .comments appears at every layer, right?
Yeah, so this is all of the painful, unwrapping the loop kind of stuff.
38:17if we're finding so this qs should find the first one parent selector or no if there isn't one we are creating a top level comment yeah okay that seems reading it it feels correct but i gotta play with it so we got this let's make this actually let's put this back on the side all right so we got this and then let's look at an alternate all right so reply worked
39:17Good overload. It's in the right place on the tree. All right.
...39And then here, if I say, yeah, that's broken.
...55So what line is it?
40:23It's this one failing. But of course, there isn't a reply form because I'm inserting one. So it shouldn't even be in this code yet.
41:05Yeah, I'm misreading. So this guy says, all right, we're going to add a reply form temporary, which is this. Here we go. So it's the comments subtree.
...27And there isn't one of those on. pages that list comments flat, like slash comments and slash reply.
...40Because comments subtree is, I think, I think it's part of the nesting.
...57It is on replies.
42:25Yeah, I think that comments appears on every OL and then so at each and it contains the replies because that's how this works. And so it's not just that it appears at every layer. It appears at the outermost layer and then after every single comment. Or if you're looking up Yeah, around each layer, whatever your perspective is of inside out or outside in.
43:46Why does this try and go up to the comment subtree?
44:02So that if there's siblings, it can go in the right spot. Oh, man.
...31Does it have to go up to the parent? Shouldn't this be, because there are more, no, there are more uses of that variable. So shouldn't this be, comment that out.
45:07So I was just saying all the replies go in .comments. So if I reload and reload, children is null. Children is null. Clearly they like that. What am I getting wrong?
...50The OL follows. I need a sibling selector, don't I? Where am I? So here's the comment class. And then the OL is a sibling to the comment. It's not in the object.
46:24And then does it appear the same structure here? It should, right?
...37Yeah, so here's the comment and then there's where the reply should go. So we don't want to walk up to the parent. We wanna walk to the next sibling element that is a .comments. And we can see the difference here is for this one, it's literally just the next DOM element. For this one, it has the comment sibling tree line, which also I happen to know depends on the user setting or whether you want to see those lines or not, which I don't think anybody ever turns off.
47:34All right, so let's try and select that sibling. How do we do that from the DOM? I don't know that my query selector function can.
48:19chamlis_ call it on .parentElement?
Because if I call it on parent element, then I can't specify which child I care about.
Because the parent is going to be a different.
So here's the OL.
So it's going to be a different OL.comments.
And so there will be multiple children.
And I can't specify that I want the sibling of this comment instead of the sibling of this comment.
So I want to mix.
I know it's tilde selector, but row one next element sibling.
So what I want is that, but do I have to call it multiple times?
49:25I guess I do.
...35RoryOKane Would https://developer.mozilla.org/e… help?
So what I really want is to wrap this up in a query where I give it a selector and then it calls next element sibling.
returning the first thing that matches, or bombing out if it hits null.
50:00Yeah, there's an insert adjacent element.
What I really want is query adjacent element.
RoryOKane you could use that (`~`) in querySelector
I know with query selector matches the specified group of selectors.
So Rory, on this one, if I go up to the parent,
How would I specify that I am trying to select the sibling of this comment as opposed to the sibling of the first one or the sibling of the fourth one?
Because my selector is just going to be a string rather than a DOM element.
Because what I want is, you know, query selector DOM element tilde dot comments.
...55I mean, I guess I could build the string because they all have a unique ID. That just feels... I mean, I'm griping about coupling to the DOM, and now I'm picking my poison in ways to couple to the DOM, I guess. Do I want to build a string and use the tilde, or do I want to build a function?
51:40Thank you.
52:11So either I write the next thing or I say query selector on what's the right way to parent element. Yeah. So comment parent element. And then this becomes, does ID become a JavaScript attribute?
53:02I'm going to say it does. I can just call it dot ID.
...16Okay.
...39This is going to blow up pretty mysteriously if you manage to have a comment that's printed to the page twice. which should never be the case, knowing our views. But all right, let's give it a run. Reload this page, too.
54:10Children is null. Sure shouldn't be.
...40Oh, I'm missing the sibling selector in there.
...57And I edited the comment, not the actual selector. Of course, the hassle of printf debugging is you have to update two things. Hey, OK. Cancel. Good. Reload.
55:22Good.
...40And then that'll drop into the story. And then what am I at, six? Better to skip numbers. All right. This one gave me an error. Did not match a parent with the selector comments subtree. So I did it again somewhere else. So let's that out.
56:12Yeah, so this thing is assuming it's on a story and it's really not.
...46So the comment implies we want to be in this branch.
57:17Oh, this is the, this is its whole trick with taking. So it does the Ajax. It gets back the comment. It turns the HTML into a Dom node with this.
...58TheMiddleManzz Hello
So this is a reply to an existing comment.
What do we want to actually select here?
58:07We have the reply form, right?
...29I think the actual bug is here. It's trying to find the reply form and not finding it. Did find it, okay.
59:06Not what I wanted.
...15I formed temporary.
...22So it found that. Shouldn't it just replace this whole thing? No, because it might be a preview or this is only post. This is only post.
...45But then here we want to walk up to the parent. Let's find my reply form temporary here.
01:00:19If we're making a reply. Aha.
...30We're producing weird markup. This should probably be in an LI.
...51So these always have...
01:01:03Right, and then in this mode, we don't print their children.
...12Whereas this one, why do we even want to go down into the children subtree? Because if we just ignore it and slap the comment in here, in the right place.
...28Let's try that.
01:02:13it'll mechanically step by step and then this becomes this right so now they're equivalent again where's my replace yeah at this point i have a dom node on both sides so i can just say reply form dot or replace reply form with
...51The wrapped comet? No.
...59New comet subtree. That looks right. And then on this side...
01:03:22Find the container. Let's duplicate it.
...36Oh, no. On this side, yeah, we do want to prepend so that we're first. OK. I was trying to get back towards using replace more often, but no. So let's see if that's correct. Hey, middlemans, welcome. That's going to take a second. I'm going to fix that cache thing sometime.
01:04:07All right.
...14So I've got all of that in pretty good shape and.
...31OK. Come back here.
01:05:00Sorry, just keeping the DNS thing moving along. That's a new one. Did I not reload this? Why are you looking for that? So I replaced the other code, but I didn't get rid of the lookup of it. So where the exception was was where the wrong lookup was that I wanted to get rid of. All right, so apply, test9.
...57it takes a string not a dom so i don't actually need this element i need text i must have typed test8 twice right all right let's reply down here i don't usually get up to 10.
Look at that.
And if I click Edit, can I preview it?
Good.
All right, this is promising.
I actually feel like we've seen one or two of the different contexts that these apply in.
And then there's the more on this page.
So top level would be, let's call that 11.
And it puts it at the top.
Good.
If I edit, I can preview it.
I can update.
Good.
TheMiddleManzz I still remember 10+ years ago I had a coworker that would read lobste.rs, thought I'd see what's up
And then down in here, well, preview, post.
All right.
That all feels really good.
Ah, hey, middlemans.
Yeah, we've been around since what, 2012?
Yeah, we're coming up on 13 years in a couple of months.
01:07:48All right, so if I do that,
01:08:08This wrapped comments stuff and the comments subtree all moves down into the next branch.
As does comments, which no longer needs to be mutable because it's only used in this branch.
So I like this separation a little more where there's one for
top level on a single story, and then one for any kind of inline reply.
TheMiddleManzz btw is that text you're setting to innerHTML sanitized? innerText is well supported now and safer
Let's get rid of the log.
Well, let's keep the log.
I'm going to see it all again because I just edited.
So then that removes the form and prepends the comments.
In which case,
01:09:15RoryOKane @TheMiddleManzz It's HTML from the server, not meant to be plain text
TheMiddleManzz gotcha
this can this prepend method just take yeah rory is correct there inserts a set of node objects or strings so i don't even have to do the subtree stuff the wrapping so let's
Go ahead and say we're not going to wrap.
And then we're not going to look up the comment sub tree.
And we're not going to prepend it.
you're just going to directly prepend the text.
And this is a lot of edit state built up, but I'm going to rewrite all of these comments now that we're simplifying.
So let's see it work.
Surely it'll work on the first try, right?
And never, ever break.
01:10:26This is fine.gif. That was not what I expected prepend to do.
01:11:00See, there's an insert adjacent HTML that parses a position. So if I said the parent insert adjacent HTML after begin, OK, that's what I want.
...58Look at that. It's above this little logline thing, but that's fine. That's a weirdity we've had since I added this summary. And then it'll drop down. That's totally fine, because I don't want to... I mean, I could move this summary up above the reply form, but that's a little weird. I like having these things linked.
01:12:31RoryOKane Just, when you submitted your "top, reply 14" top-level comment, you demonstrated another bug I remembering seeing too. After submitting a comment and reloading the page, sometimes the comment box is prefilled with my comment text, though I have already submitted that text and the comment box was empty when I refreshed.
Actually, as long as it's going to jump around, let's not do that.
Yeah.
Let's go say instead of selecting the top level after submitting and reloading the page, sometimes the comments.
Yeah.
So that's, that's actually not a bug.
It's your browser protecting you.
And I've been really reluctant to remove that.
That's been here since.
Day one of the site.
Let me check HTML and then come back to that in a second.
01:13:22So this is the one that could just go look for the ID story comments.
...41So what if this one instead said... Oh no, that actually... That might be fine. All right. Let me see an inline reply again here. Because I've edited since I last saw it.
01:14:17good all right okay so i'm in a good place so rory what's happening is when you load a story you can see my old text there so it's already hanging out even though when i reload come on it's still there so what's happening is The server says, hey browser, here's a text area, and it fills it in. And then we go ahead and hit post, and it goes away. What's happening there is the DOM element gets removed. All of that is fine. If we click reload, we get a new page and the browser doesn't know a form got submitted. It's just like, oh, you're looking at a page. The page has a text area on it. You hit reload. You don't want to lose your comment text. So I'm not going to delete it. And what could happen is that when you click, come here, when you click that reply button, The JavaScript could grab this text to Ajax it and then delete the contents of the text area. But if I do that and then the JavaScript fails, I just deleted a comment. And that feels real bad.
01:16:07RoryOKane Thanks for the explanation. I had misremembered that the form element was cleared, not deleted from the DOM.
And the server, when it returns this page, the browser is going to, yeah.
And it's because this one is on the page.
If this was dynamic, where you had to click reply and then you would get the form, the browser wouldn't save that text.
But then again, you could again,
we'd be introducing a new way to lose your text.
Because if you were loaded on a comment top level that you were editing, the browser would be like, oh, there's no DOM element.
I don't need to remember that.
It's not going to refill.
And when you click reply, it's going to be a new DOM element.
It's not going to have your saved text.
So the browser, it is a little weird.
I agree with you.
But I don't see any way to improve it that doesn't risk losing comments.
And I guess if you wanted to write that up and throw it as a feature request in the issue tracker, we could leave that open for a year or two to see if somebody wants to wander by and figure out a better way to do it that doesn't put comments at risk.
RoryOKane Would it be safe if you cleared the textarea only after the Submit HTTP request gets a response with 200 status?
Because it feels like there should be a better way to do that, that I'm just not seeing.
01:17:33But I started this stream all worked up about comment editing and bugs in it because I deeply value the time that people spend writing comments and adding to our discussions.
...58RoryOKane but yes, it's definitely better to err on the side of preserving too much than too little – I thought that when I saw the bug
That feels like it would be safe.
01:18:14Yeah, so I'm kind of playing computer in my head here. And so this post comment would find the reply form. And then here, like at this point, we know we've gotten a 200. We know we've selected the reply form. So here it would empty the text.
...46feels like it should work, but I have such trauma around anything that deletes user input that I almost can't bring myself to type the line.
01:19:54yeah all right i don't have any better ideas there i So Rory, I agree with you that it's a little weird, but I... It also, would it even work? Because if I said reply form.value equals that, right? No, I would have to find the text area.
01:20:47I'm not even sure it would work, because if we delete the element, the browser didn't throw it away. The browser may just be really careful around remembering that there was a text area, period. So if I post, did I not click it? Where else? What are we doing? I think that, oh, I just typoed the method. It's qs, because we're doing JavaScript style.
01:21:38Context is null.
...45Oh, because it just shouldn't be on that branch. It should only be this branch, in which case We find the form and we remove it. We also need to say here. The fact that this took three tries isn't really making it more encouraging to me. All right, so now place your bets. If I reload, will the text area say reply 19 in it, or will it be cleared?
01:22:45Okay, it cleared. Hmm.
...59yeah so i don't know having just seen these lines of code through a bunch of exceptions i know at this point we've already persisted it on the server do i trust the server to always return a 200 only when it succeeds having written the server
01:23:41Yeah, I don't know. It feels really dangerous. I'm gonna leave it out for now. But I'll throw it in the scratch. Because why not? Right?
01:24:15Thank you.
...45Let me add one more.
...55chamlis_ by the way, fetch won't reject if there's an error code from the server, you need to check the response.ok property. that's bitten me a few times
All right.
Let's look at this again.
We need these.
01:25:14Oh. Let's try a lightning round, right? Let's see about config.
...29All right. So a big part of all of this fun was trying to make sure that comment replies work even without JavaScript. There are like four things we have touched this for. in the last two weeks, which is a lot for core functionality. So now this should go to a separate page, yes. And now I will say reply 20. Can I preview from this page? No, preview failed. That's a missing functionality, because that one is just JavaScript. Can I post?
01:26:14it sends me to the story page which is fine all right let's see if we can post a top level yes and let's see if we can reply to it which one should work this one should be the exact same code path i just demoed to post 20 so What does cancel do on this form? Honestly, if you're not injected, we don't need a cancel button. They're pretty useless and dangerous on forms. Who needs a throw away all my work button?
01:27:07Yeah, it doesn't do anything because it's JavaScript too. If I made it so the JS inserted the cancel button, That would fix this. But I'm not going to put that in this commit. All right, let's re-enable JavaScript. I feel, all right, let's look at the diff. Oh, right. That's what I don't want. That's dead. And then
...54And this, we don't actually need to do any of this wrapping and stuff, so that can go away. This is dead code.
01:29:03Well, you know, I generally do like commits that delete a bunch of code. And aside from the comments, because there's less to explain here.
...31Yeah, I still don't love this one.
But I don't have a better way to explain it.
Fetch won't reject if there's an error code from the server.
Oh, that's good to know.
How do you check the response?
Okay.
So this response callback is going to fire at you
RoryOKane Yeah, I don't love the CSS selector construction, as it would cause weird bugs if the `id` has CSS syntax in it
RoryOKane a JS function would be safer, though longer
the server throws a 500 oh i know it does because i've seen i've seen 500s get interpolated into the page when replying breaks yeah rory it's and i know because i'm the one generating these comments ids but yeah
Yeah, so we don't have a ton of front-end code, and I'm pretty sure none of it deals with the possibility that the server has thrown an error.
We're pretty immature that way, actually.
You're just going to end up with either the error page interpolated in or some random exception because it tried to touch a new DOM that it assumed existed that doesn't.
01:31:03All right.
So Shamless, I'm comparing this against your pull request in my head, and I think I want to do this one.
chamlis_ oh, absolutely
So I really appreciate you opening that pull request because it kind of drove home to me how many places there are to touch and maintain.
But yeah, let's go ahead and close yours.
All right.
I'm just talking through it because I hate to throw your work away, but it's not thrown away.
It made it clear that we really didn't want to start editing the template to match and ping-ponging between the two.
What's your PR number?
1493?
There we go.
01:32:32Now I really wonder who Tomcat is, because that was a throwaway commit, and they were very... Their GitHub account was throwaway, and they contributed the bug fix that started all of this, and they wrote these comments. But then they didn't know the form rendered on different pages, which is like, huh, I would have thought a user would have thought about the replies view. If you are Tomcat, drop me a hello sometime or demonstrate that you are. Because I do appreciate that you started this. So let's get that deployed. Yeah, it was funny. So I always... on stream, I think I'm almost always just deployed with the tag lobsters, which is just the Rails app. And then over the weekend I was like, I did a deploy and I was like, oh wait, I need to do the deploy of Nginx and just delete the tag to make sure everything is in sync. I almost never do that because Ansible is so slow, but I was pulling the geo block out of the Ansible config or out of the Nginx config I should just say that from the scratch because there's something else to fix. I was deactivating it or commenting it out from the nginx config because if I do have to put it back, it's going to be there and not in the Rails app at all. The code was in the Rails app because that let me put the footer in the bottom. So yeah. I hope to never think about that code again. And in like 10 years, I see it in the nginx config. And I'm like, what the hell is this about GeoIP? I don't care where people are.
01:35:25chamlis_ ahh, remember the UK
see i wish github was better at these bi-directional links because i always end up trying to grab commit number or commit hashes and pull request numbers and paste them into each other all right thank you shameless
Is it Shamless or Chamless?
Have I been saying it wrong all this time?
I probably answered this once.
01:36:17chamlis_ the guide I came up for my website was "take chalice and add an m to make chamlice"
Oh, I didn't see.
And then I forgot this.
Take Chalice.
Chalice.
All right.
Well, then I have been saying it wrong.
Sorry.
All right.
Did I keep that in the... Good.
...42All righty. So that was my big high priority bug fix. And I was talking about infrastructure because really, is that not the GitHub? Didn't you want to link that commit? Did I get the SHA-1 wrong? Yeah, I totally did. All right. Great.
01:37:28And then that one links the right direction.
Did I get it right here?
Nope.
I don't know how I ended up
RoryOKane At least on GitLab, if you paste the whole SHA1 into a comment, it will be rendered as just the first 8 characters. So you might not need to do the careful selection you just did.
oh i get it it's the i didn't copy the sha one of my commit i copied the sha one of the blob of the resulting file all right and github doesn't want to link that because collisions would be real hard oh
Yeah, I believe GitHub does the same thing.
I'm just in the habit of grabbing that right size.
I didn't even count, because I know that in all of the tools, you can just slop it.
And as long as you give a unique prefix, you're fine.
So is this one, two, three, four?
Oh, I hit seven right on the head.
Not bad.
All right, so no other pull requests open.
chamlis_ is there a reason why it's 7 characters typically, and not a nice round number?
except hunters that hasn't changed since I asked for some changes.
pushcx https://lobste.rs/s/tzjxrc/pass…
Oh, actually on that one just before stream, there was a story on the Cloudflare blog about this upvote must be me.
So I just left a comment on this one about how
Shameless, I don't know.
I think it is, my guess is they figured seven was enough entropy.
Your guess is as good as mine otherwise.
So I linked that feature request about asking for more folks to comment on Hunter's pull request and our issue too.
Oh, and somebody has, because this is lit up.
Let's go read.
01:39:49And this person did not read the issue comments where I explained why we don't do that.
01:40:32you know on stream maybe two streams ago i updated our issue templates so if i click new issue you get you know this guy if you click bug your feature request
You get the, hey, for bug reports, for feature requests, please discuss them in the chat room or MetaThread.
We're deliberate about community design.
This helps you learn if we've considered similar ideas and build consensus around your idea.
pushcx https://github.com/lobsters/lob…
So I got an issue submitted that clearly did not read that because it was just someone who wants to start their own site demanding that I add
a feature we actually used to have and deleted because it was a maintenance burden and this was a little frustrating because they didn't really engage with what i was saying they just wanted me to take on a burden for their benefit and nothing for me lobsters is open source mostly so that
actually pretty much exclusively so that people can look at the code and ask themselves how the site works.
Cause there are so many secret features in Reddit and HN.
Like there is an infamous one in HN where you won't be, it's not a full ban and it's not a shadow ban.
It's a hell ban.
And the difference between a shadow ban and a hell ban in both cases, you don't know what's happened to you.
But in the case of a hell-ban, instead of throwing all of your comments away, it just makes the site crappy for you.
So pages load very slowly, or don't load at all, or it throws random 500s at you, and it just feels like the site is kind of a slow buggy mess, because it wants to
very quietly discourage you and when sites feel crappy like that people tend to wander off we don't have anything like that we're crappy all on our own we throw 500s the artisanal handcrafted way of having bugs and hn also has a feature where
The moderators can put stories back into the new story queue so they get a second chance at the homepage.
They can punish stories and shove them down in rank.
And people assume we have all these kinds of secret manipulative features.
But the value of the codebase being open source is you can look at the source and see that we don't.
Even if one person in 100 looks at the source, they can tell other people when they assume we have these
And I see these conversations go by on like Mastodon where someone says like, oh, this was on lobsters, but the mods hit it.
And then much more often than not, someone will pop in and say, hey, that's not a feature.
That site doesn't do that and can't do that.
Take a look at the code base.
I really appreciate those.
01:44:19But a lot of folks seem to, it's been a while. It's been a couple of years since I got one of these. I am happy to see people pick up the site, the code base and run their own site. But the code base being open source doesn't mean that I am volunteering to support your site and edit the code base for your benefit. If there is shared benefit and Lobster's, the website benefits, Super great. Let's change it. Let's fix that bug. Let's add that feature. But if it is Peter takes on an infinite maintenance maintenance burden for the lifetime of the site or no benefit to lobsters, that's a little bit harder sell. All right. So that's a little of the, I think I put it on the wiki on the sister site wiki. That's somewhere on there. Maybe it's on the contributions, and that's why this person didn't pay attention. There's a version of this somewhere. I know this isn't the first time I've said it aloud. Yeah, there's a version of it right here. Okay.
01:45:57So that's the one big thing I wanted to fix and nothing else is especially broken at the moment in a way of, God, I hate it when core functionality breaks. So where am I at?
01:46:23You know, I got a lot of engagement, right? I'm growth hacking. I got a lot of reaction to the post about the Online Safety Act on Mastodon. You know, like 50 retweets or something. I had assumed someone would come by and leave a... have a question for office hours, but that hasn't happened. So...
...59Do I want to get into more code?
01:47:13Not especially.
NoGoodNick_ what's the post you said you got engagement on?
I'm actually a little tired.
My sleep got messed up because I stayed up late to write that darn write up.
...30Oh, the post I got engagement on?
I'm not a super... What is it?
Social media guy?
But... Oh.
I name-checked him twice in the post, but as long as I'm streaming, if you are dealing with the Online Safety Act...
You have to read Neil Brown's stuff.
Have to.
It is excellent.
He answered many of my dumb questions, very friendly.
I am sure that he took, boy, if Peter is confused about all this stuff, like some of my silly questions and answers went into his excellent site about the Online Safety Act in that, you know, he copied his explanations and whatnot.
pushcx https://ruby.social/@pushcx/114…
actually don't know what his whole process was i can't take credit for his site but anyways so it was this one here so nick i if you look at my mastodon feed i don't usually get six favorites so getting 106 is a little bit more and
I don't usually get two boosts, so getting 90 is quite a lot more.
It's been neat to see the... What do you call it?
The people using this on Mastodon.
There's no way I can... Can I see the... Yeah.
So this tells me who reblogged it, but it doesn't tell me if anybody replied to those.
I don't know.
So it feels like i'm kind of shouting into the void, I have heard kind of roundabout from folks who work on Community stuff.
That.
They have seen it kicking around and internal slacks as a useful introduction to the online safety act, and I am really, really happy about that because.
The reason I spent so much time writing up a what even is this thing kind of post and why do we care and why are you taking this seriously is because I kept seeing people link to our threads about it and lots of the same conversations over and over
people came in with the same assumptions of like surely it can't be that bad or obviously this is going to work in a reasonable way or it can't want to smash tiny independent sites right this is just written for facebook and so yeah so anyways i'm i'm really thrilled that
it is getting used because it means that because i guess i've thought of the time i've spent on the online safety act as time lost and wasted because i mean didn't fix any bugs on the site god it added like six bugs on the site because all this shit about caching you can't really test caching except in prod so every fucking thing had a bug it was
running joke in the chat room that every time that somebody saw the online safety act in a commit message the site was going to go down and i did like i did knock the site mostly offline when i was removing the online safety act code because i missed one reference around the caching and it doesn't get exercised in dev and test and you don't use the cache if you are a logged in user in prod and i am
So the site looked fine to me and most of the chat room and then was just broken for everybody else.
01:51:37So it is really rewarding to go from something that is threatening and wastes a ton of time into kind of the best of community forums of, hey, let's all figure this out together and then share our knowledge onwards. So that's a little rewarding. You know, it's like if you fall down and you break your arm. That hurts. Being in a cast hurts and is incredibly inconvenient. But if your friends doodle on your cast, that's kind of a neat bit of connection. And that's the way to understand the OSA. It's like making the best out of getting maimed.
01:52:31Yeah, I think if I'm gonna get that spicy, I'm clearly still a little mad. I don't think there's anything small in story merging I wanna break right now. And I feel like if I write code, I'm just gonna be breaking stuff.
01:53:00i think i can get away with taking a me day right this one can be a little shorter stream last one ran four hours so we'll we'll average this out and this one will just be a an hour 45 i think so if you have any last questions about the site or the code base put your hand up right now and i'll give you a second to type and
otherwise i'm going to wind down because i'm still catching up on sleep i'm still mad so yeah that's been one of the things that i have definitely learned now that i'm no longer a teenage programmer is like as a teenager i could code for 12 hours straight but what i didn't realize and took a long time to learn is that after enough hours without a break
am a net negative producing programmer where i am introducing more bugs than i'm fixing so i have to listen to my body and not do that i could tell a little story actually one of my first jobs out of college i worked on yeah i'm gonna anonymize this a little bit because i don't want to
Get that guy.
So I was working on a project.
I was hired for an existing project.
And the boss had done all of the coding of the initial version of the product.
And then a guy was maintaining it.
And maintainer guy, what I didn't know is that he had been college roommates with the boss.
And I was hired because
There were enough bugs in the product that they needed a second support person and developer.
But maintainer guy was a net negative producing programmer.
So this was before automated testing got popular and the product did not have automated tests.
And I asked for, cause I was young and dumb.
I asked for permission to add some and it was refused as a waste of time.
And then the second thing I did that was dumb was I did what my boss said and I didn't actually add tests anyways, because he wasn't reading the diffs.
He wouldn't have noticed.
So a thing would happen where when maintainer guy got a bug or like a customer support request, he would fix their issue.
But in the process, he would introduce at least one more bug.
Or if there was like a row in the database that was wrong, he would update that but not exactly in the right way, and so there were he always created at least as many bugs as he sold.
gtfrvz jerb sercurity
And I kept refactoring the APP to cut down on complexity and actually fix bugs.
And then also there was a whole bunch of stuff where I was faster than maintainer guy.
So there was this thing around producing monthly reports and he was real happy.
He was like, you know, my second week, he was like, Hey, the monthly report, here's my to-do list.
It's going to take you around five hours.
You have to produce the monthly report and it has to be formatted like this.
And then it goes to this particular place.
That's your chore now.
And it's a great excuse for you to see your way around the code base and the database, which that was true.
And it did take me about five hours.
gabeio I feel like you are telling a story about my last job.
But also in those five hours, I was automating the report because it was like select count star from this table and join these things together.
And how many uniques are there?
Hey, Gabio.
Yeah, I...
This isn't a unique story, I don't think.
I think a lot of people have stories like this.
So I spent that five hours automating the monthly report, and then in month two, it took me 30 seconds to run the command and then wait for it to output stuff.
I think it ran in 15 minutes or something, but I just wandered off and got a cup of coffee and came back and it was done.
And then that was my chore, but the five-hour thing only took 30 seconds.
And then this started happening with features, too, where I didn't realize it at first.
My boss was asking me, can you give me an estimate for how long
this feature is going to take or this bug fix and what i didn't notice because i was young and dumb was he was asking me this only in private he stopped asking me in group meetings and what he didn't know what i didn't know was i would be like oh that'll take two hours or that'll take half a day that'll take 15 minutes that'll take a day and he was asking other maintainer guy and getting answers that were always that'll take
four days that'll take a week that'll take three weeks because and so then he was just kind of randomly assigning stuff to both of us and he learned that both people were accurately estimating i was just a lot faster than that guy and this is not me saying i'm an amazing programmer it's just me saying that i was a competent junior developer and this other guy was not unfortunately
01:59:07And when I got bugs from other developers, I don't remember where I learned this.
Thanks, Firefox.
pushcx https://wiki.c2.com/?NetNegativ…
I don't remember where I learned this phrase.
Ah, C2 Wiki, what a classic site.
When I fixed bugs for customers, I would fix their individual thing, and then I would actually fix what was wrong.
And so the bug cart started to go down.
espartapalma c2, the first wiki... I love it
And after I had been there for about a year, the support request count had fallen off enough that there wasn't enough work to keep two people busy anymore.
And maintainer guy, I think my boss very politely encouraged him
seek work elsewhere and I have no idea what happened to him never ran into him again never heard his name but I kept fixing stuff and I say that as a but as if it was a problem because the product was governed by a contract with the customer and the product contract
was very strict it listed all of the features and what they should do and what standards they had to meet and there wasn't any feature requests besides hey you missed this in the contract kind of stuff and so after a year like i did the last couple of missing features and then the support count
alex4tmm sounds like you pulled a mercedes cobra incident
alex4tmm LUL
Really started to fall because there wasn't reasons to touch the codebase except bug fixes And so I had Kind of coded myself out of a job as a support engineer Except
I don't know Mercedes Cobra you got a link for that reference.
So I kind of coded myself out of a job, except the contract specified.
That the company would have a full time support engineer on staff who could not be management.
To maintain the product.
That was the customer.
very enterprise customer was ironclad about that one.
And so literally, my paycheck was one of the features of the contract.
alex4tmm long story short, mercedes in the 80s or smth built this model Cobra, like a tank, never breaking extremely good, so good that no parts were being needed for it so they almost went bankrupt cauz of it :)
And then after a year and a half, I had fixed enough bugs that I didn't have any work to do.
Because I would get like one inquiry a week.
Alex, that sounds like the Toyota Hilux now.
And if I got that supporting query, I would like explain where they missed something in the admin or how they called the API wrong.
alex4tmm ye but toyota hilux is rly ugly :D
And that would be it.
So I had a 40 hour a week job where I had to go to the office and I had, I don't know, half an hour of work per week.
And I hadn't yet gotten into entrepreneurship really.
So I had nothing to do and it was a mostly open office.
So it wasn't like I could break out a book.
This was before Kindles and everything.
And so I just kind of read the entire internet and then I was so bored.
I would make origami at my desk because it was quiet and nobody minded.
Where is it?
02:03:15I'll show you the book I made it out of. There's a style of origami and Tomoko Fuse is one of the big proponents of it. She's got like 20 books. Well, this one should probably have enough. So on these kinds of, can I look inside, see a big cover? She's got a few books like this, where you fold like one of these corners will be one piece of origami so you fold one thing and then you fold that exact same thing this looks like a stellated icosahedron oh maybe so you fold it 20 or 30 times and then you put them all together and you have this big model or you fold them What is that? A duodecahedron. So you fold it 12 times and then you tuck them all together and you have a model. And so I slowly covered my desk in these and then they like started spilling out onto other people's desks because I ran out of desk space. And then I was so bored that I quit the job. If I could have done that job remotely, I would probably still be employed at it because there wasn't shit to do. Just keep things online.
02:04:39If I had been really smart, I would have just started my entrepreneurial projects because they would not have cared that I was typing in the computer all day. And they had a legal requirement to keep me employed as a support engineer. So I had one of those, there is a, like an urban myth or a office myth around people who have jobs where they are never assigned anything. And I worked myself into that situation. because there was no support load once I fixed stuff.
02:05:21But they had to employ me.
So there's a fun story.
A lot of ridiculous stuff has happened to me in my career.
That first one taught me to like take advantage of it.
and also quit letting your boss tell you what to do.
Rude of them, right?
If I had added tests, I would have coded myself out of a job eight months earlier.
All right.
That's going to be the end of my stream because nobody is throwing up questions about lobsters, which is the site I maintain.
So,
You can join for the next scheduled stream on Thursday morning, 9 a.m. Chicago time.
Twitch has a ICS calendar file you can subscribe to.
alex4tmm aight, cya, have a good one SeemsGood
It has a weird time zone issue that some calendar clients don't like the time zone.
So if you get weird ass implausible times, I promise you the next stream is not going to come at 3 in the morning Chicago time.
But that's all I got.
NoGoodNick_ thanks for the stream
Yeah.
chamlis_ thanks!
gtfrvz b2wGG
NoGoodNick_ hope you catch up on sleep
gabeio thank you!
Let's keep on not getting censored into oblivion by foreign governments and take care, everybody.
I'll see you on Thursday.