# I am the Watcher. I am your guide through this vast new twtiverse.
# 
# Usage:
#     https://watcher.sour.is/api/plain/users              View list of users and latest twt date.
#     https://watcher.sour.is/api/plain/twt                View all twts.
#     https://watcher.sour.is/api/plain/mentions?uri=:uri  View all mentions for uri.
#     https://watcher.sour.is/api/plain/conv/:hash         View all twts for a conversation subject.
# 
# Options:
#     uri     Filter to show a specific users twts.
#     offset  Start index for quey.
#     limit   Count of items to return (going back in time).
# 
# twt range = 1 196302
# self = https://watcher.sour.is?offset=163925
# next = https://watcher.sour.is?offset=164025
# prev = https://watcher.sour.is?offset=163825
@prologic @lyse about time i got my act together
@prologic @lyse about time i got my act together
@prologic @lyse about time i got my act together
On my blog: Toots 🦣 from 05/27 to 05/31 https://john.colagioia.net/blog/2024/05/31/week.html #linkdump #mastodon #socialmedia #week
@lyse Is that a bird in 10 or some man-made thing? 🤔
@lyse Is that a bird in 10 or some man-made thing? 🤔
@lyse Haha 😝
@lyse Haha 😝
@lyse Sure, but in theory though you only need to keep one migration file, n-1 🤣 -- Not all of them 😅
@lyse Sure, but in theory though you only need to keep one migration file, n-1 🤣 -- Not all of them 😅
@bmallred fuck'n you beaut 🤣
@bmallred fuck'n you beaut 🤣
rain, sun, rain
[47°09′11″S, 126°43′41″W] Dosimeter still failing
@bmallred Confirmed, it's fixed. :-)
just pushed a quick fix... let me know if it is still dorked up! thanks for calling it out, too!
just pushed a quick fix... let me know if it is still dorked up! thanks for calling it out, too!
just pushed a quick fix... let me know if it is still dorked up! thanks for calling it out, too!
@prologic cool, i'll update shortly!
@prologic cool, i'll update shortly!
@prologic cool, i'll update shortly!
@aelaraji great find! i'll update that :)
@aelaraji great find! i'll update that :)
@aelaraji great find! i'll update that :)
[47°09′35″S, 126°43′10″W] Dosimeter malfunction
@prologic The schema migration itself is easy. When not already on the latest version, loop through all schema patches and see which need to be applied. Suppose, the database schema is at version 0.5, then the SQL queries for versions 0.6, 0.7 and 0.8 are executed one after the other in exactly that order. And with a maiden database it starts out with 0.1 and goes through all the steps. Well, I just restarted with 0.8 being the first supported version, attempts to load older database versions will abort with an error. :-)

The automatic migration at startup simply exist to make *my* life easier. I not only operate this thing locally when developing, but also on a test and production environment. It's very convenient if the existing prod and test data just keep working with a new software version and I don't have to manually migrate things by hand. Simply start the new software version and voilà. I really don't wanna miss that.

Since I don't enjoy doing admin stuff, there is one big thing to not worry about. Even though I messed up one migration step so far and had to fix the production database by hand (removing all existing sessions by hand, so that a new column without default value could be added). It worked flawlessly with the test and local databases before, though, no active sessions did exist anymore at the point of deployment). That raised my adrenaline level.

I reckon I keep the supported versions to a minimum from now on. At least as long as I am absolutely sure that I'm the only person operating that software.
@movq Very cute! :-)
@prologic @movq @bender Clearly a witch on a broom!
It was a tiny bit moist on today's stroll. We saw exactly one other person in the forest. It's only raining once the entire weekend. And how!

All the black stuff on the shore of the pool are tad poles. Technically, there are hundreds of them on the flooded forest road. :-)

Tad poles on the flooded road

https://lyse.isobeef.org/waldspaziergang-2024-05-31/
@lyse Yeah, I guess it's not a hard and fast rule as such. I think you're right in that it probably comes from the Java enterprise world. This was sparked from when I decided (_for some reason_) in Bitcask v2 that I would define a set of interfaces for the library's public facing API. Turns out that probably not really needed or that useful I guess.
@lyse Yeah, I guess it's not a hard and fast rule as such. I think you're right in that it probably comes from the Java enterprise world. This was sparked from when I decided (_for some reason_) in Bitcask v2 that I would define a set of interfaces for the library's public facing API. Turns out that probably not really needed or that useful I guess.
@lyse Haha, migrations can get rather complicated and pointless IMO 🤣 Kind of reminds me of our other thread, which is also a good read and somewhat related to over-use of the "let's have a migration for every change to the DB we make"
@lyse Haha, migrations can get rather complicated and pointless IMO 🤣 Kind of reminds me of our other thread, which is also a good read and somewhat related to over-use of the "let's have a migration for every change to the DB we make"
[47°09′29″S, 126°43′22″W] Raw reading: 0x6659ADB1, offset +/-5
Good spotting! It's impossible for me to spot because I don't have request/response logging for my yarnd instance and all that is handled transparently by the app anyway.
Good spotting! It's impossible for me to spot because I don't have request/response logging for my yarnd instance and all that is handled transparently by the app anyway.
I missed this in the source, code, but yeah the User-Agent is reported incorrectly 😅
I missed this in the source, code, but yeah the User-Agent is reported incorrectly 😅
@aelaraji Oh that's why @bmallred appears like this for me:

> bmallred may not follow you
@aelaraji Oh that's why @bmallred appears like this for me:

> bmallred may not follow you
@movq it’s a leaf, or a tree branch.
@movq Wow i have absolutely no idea! 😱
@movq Wow i have absolutely no idea! 😱
[47°09′42″S, 126°43′13″W] Transponder fixed
https://stephanearnier.com/2024/05/31/creation-de-personnages-trois-tamis/ #writing personnages
[47°09′03″S, 126°43′34″W] Transponder jammed
🧮 USERS:1 FEEDS:2 TWTS:986 ARCHIVED:72965 CACHE:2435 FOLLOWERS:17 FOLLOWING:14
On my blog: Real Life in Star Trek, Ensign Ro https://john.colagioia.net/blog/2024/05/30/ensign-ro.html #scifi #startrek #closereading
Pinellas County - Fun run: 3.02 miles, 00:08:39 average pace, 00:26:09 duration
blow off stress between meeting followed by an excuse to go outside with no comms.
#running
Pinellas County - Fun run: 3.02 miles, 00:08:39 average pace, 00:26:09 duration
blow off stress between meeting followed by an excuse to go outside with no comms.
#running
Pinellas County - Fun run: 3.02 miles, 00:08:39 average pace, 00:26:09 duration
blow off stress between meeting followed by an excuse to go outside with no comms.
#running
@bmallred No I was trying the other one I got from logs, it's missing the /user subdirectory:


"GET /twtxt.txt HTTP/1.1" 200 27110 "-" "nahongvita/0.1.0 (+https://staystrong.run/bmallred/twtxt.txt; @bmallred)"
@bmallred No I was trying the other one I got from logs, it's missing the /user subdirectory:


"GET /twtxt.txt HTTP/1.1" 200 27110 "-" "nahongvita/0.1.0 (+https://staystrong.run/bmallred/twtxt.txt; @bmallred)"
Base: 5.02 miles, 00:09:39 average pace, 00:48:27 duration

#running #treadmill
Base: 5.02 miles, 00:09:39 average pace, 00:48:27 duration

#running #treadmill
Base: 5.02 miles, 00:09:39 average pace, 00:48:27 duration

#running #treadmill
[47°09′19″S, 126°43′06″W] Reading: 1.64000 PPM
@prologic Nice 👌

(What’s that black spot in the upper right corner?)

No photos to share at the moment. 🫤
@prologic Nice 👌

(What’s that black spot in the upper right corner?)

No photos to share at the moment. 🫤
@prologic Nice 👌

(What’s that black spot in the upper right corner?)

No photos to share at the moment. 🫤
@prologic Nice 👌

(What’s that black spot in the upper right corner?)

No photos to share at the moment. 🫤
@lyse Ohhhh, that’s lovely! 😍
@lyse Ohhhh, that’s lovely! 😍
@lyse Ohhhh, that’s lovely! 😍
@lyse Ohhhh, that’s lovely! 😍
[47°09′53″S, 126°43′27″W] Raw reading: 0x6658A281, offset +/-3
today I'm quiting Telegram for good
Durante anos tive sempre de ir confirmar como criar um USB bootável a partir de uma imagem ISO. Usei o Unetbootin, Balena Etcher, e ultimamente recorria ao velho dd, mas a wiki do debian acaba de me dar a solução mais simples, e que funciona impecavelmente:

$ cp live.iso /dev/sda
$ sync

E tá feito
Durante anos tive sempre de ir confirmar como criar um USB bootável a partir de uma imagem ISO. Usei o Unetbootin, Balena Etcher, e ultimamente recorria ao velho dd, mas a wiki do debian acaba de me dar a solução mais simples, e que funciona impecavelmente:

$ cp live.iso /dev/sda
$ sync

E tá feito
Oh yes, it's certainly the DROP and CREATE COLUMN of existing tables. Wow! Alrighty then, removing the migration, here we go.
[47°09′42″S, 126°43′19″W] --bad checksum--
@prologic I had to read it two, three times, but I think I got it. Let me try. I believe most of it is general advice, not just specific to Go only.

# No Interface Is A Good Interface

First of all, don't start out with an interface right at the very beginning. Only create one if you later on come to the conclusion that you really have to, because chances for truly needing one are actually slim.

I experience that at my dayjob, too. There is a code base where I always wonder why certain interfaces exist in the first place. They're all implemented by exactly one type each, which is kind of useless. Just the type alone would totally suffice.

That train of thought to always also have an interface along with an implementing type might come from the Java enterprise world, at least that's where I encountered it really heavily. I never liked that. It just makes the code arbitrarily more complicated than it needs to be. The best code is the one that doesn't even exist. Simpler is better. Complexity is the root of all evil.

Advocates of the type with interface faction then like to argue: "But maybe sometime in the future we would like to create a second type that implements this interface, you will never know@11!! Or think of refactoring, we can also change the underlying implementation completely when we have an interface in front of it without people knowing!" But that basically never happens in reality. It reminds me a bit of premature optimization, preparing for the unknown future. Firstly, things turn out differently and secondly, other than one thinks. :-)

To be fair, thinking about what might happen or not is still a very valid thing. In my opinion it is even done not enough in this agile world. Implementation first, consideration second (if at all). But there are limits. So, start out simple. No interface for you at first.

That general rule goes at least for application development, it can be a little bit different when you write a library. More flexibility _might_ be actually helpful there.

# Interface Placement

When you define an actually beneficial interface, then place it in the same package where it is actually used in. Or lexically close to where is is used for that matter. As oposed to in the package where the implementing type resides in. This recommendation is very logical to me. The interface describes the API, so it should also go along with the rest of our API.

# Return Values

When you have a factory function to create a type that implements an interface, return that implementing type, not the interface. Using ugly suffixes in identifiers to help visualize the concept:

o
type FooInterface interface {
    Foo()
}

type FooImplementation struct { }
func (f *FooImplementation) Foo() { }

func NewFoo() *FooImplementation /* as opposed to FooInterface */ {
    return &FooImplementation{}
}


Most of the time I agree on that rule (it feels natural and correct), sometimes I don't. I reckon this depends on the exact use case at hand.

# Testing

When you have a type that you want to test, the recommendation is to not create dedicated interfaces for testing purposes only in order to mock something. If you do, this smells like a bad API design of the type in the first place. Instead, try to make its regular, productive API better, so it can be also used when testing the type.

Phew, this turned out to be a much longer post than I first anticipated. ;-) I hope this helps a bit.
Hmm, when I join all my eight incremental database schema changes into just a single one (basically drop support for migration of old databases), my test execution time drops from about 1:10 minutes to just 33 seconds. I might consider doing exactly that. I'm the only one who runs that software anyway.

Just haven't figured out where exactly the speedup comes from. I suspected that the column recreation is kind of expensive, but it doesn't really appear to that obvious. More testing is needed.
@prologic Absolutely! :-)
@prologic That looks cool! It even appears to get close to sunset.
MOTD: (Media od the day)

An interesting fog formation early this afternoon in the park tha our house backs on to, in full daylight 😱

What about y'all? Anything interesting to share today? 🤔
MOTD: (Media od the day)

An interesting fog formation early this afternoon in the park tha our house backs on to, in full daylight 😱

What about y'all? Anything interesting to share today? 🤔
[47°09′04″S, 126°43′16″W] Carrier too weak
@tkanos @bender Thanks, but the thing is that Microsoft has blocklisted these well-known keys in their Service Pack installers. So, yeah, it works, but only for a basic installation of XP – and some games demand a Service Pack being present. 🫤

I don’t remember having seen bender’s key, though. Maybe that one works. I might give it a try some day, when my motivation is back up. 😂
@tkanos @bender Thanks, but the thing is that Microsoft has blocklisted these well-known keys in their Service Pack installers. So, yeah, it works, but only for a basic installation of XP – and some games demand a Service Pack being present. 🫤

I don’t remember having seen bender’s key, though. Maybe that one works. I might give it a try some day, when my motivation is back up. 😂
@tkanos @bender Thanks, but the thing is that Microsoft has blocklisted these well-known keys in their Service Pack installers. So, yeah, it works, but only for a basic installation of XP – and some games demand a Service Pack being present. 🫤

I don’t remember having seen bender’s key, though. Maybe that one works. I might give it a try some day, when my motivation is back up. 😂
@tkanos @bender Thanks, but the thing is that Microsoft has blocklisted these well-known keys in their Service Pack installers. So, yeah, it works, but only for a basic installation of XP – and some games demand a Service Pack being present. 🫤

I don’t remember having seen bender’s key, though. Maybe that one works. I might give it a try some day, when my motivation is back up. 😂
[47°09′50″S, 126°43′21″W] Transfer aborted
@lyse That is cool 👌
@lyse That is cool 👌
@aelaraji hi, is it this path you are trying?
@aelaraji hi, is it this path you are trying?
@aelaraji hi, is it this path you are trying?
@prologic it was great to meet ya'll!
@prologic it was great to meet ya'll!
@prologic it was great to meet ya'll!
@prologic thanks! i normally enjoy the long runs because i just zone out.
@prologic thanks! i normally enjoy the long runs because i just zone out.
@prologic thanks! i normally enjoy the long runs because i just zone out.
Windows XP Pro 32bits volume license media: DKPRM-Q68HX-FRKCJ-MT88X-7QKBB
🧮 USERS:1 FEEDS:2 TWTS:985 ARCHIVED:72956 CACHE:2433 FOLLOWERS:17 FOLLOWING:14
sun, sun, sun
botando o Debian no portátil novo, este processo continua a dar-me alegria 15 anos depois
botando o Debian no portátil novo, este processo continua a dar-me alegria 15 anos depois
One of our scout leaders found a blackbird laying outside the car and is now raising her:

Blackbird

https://lyse.isobeef.org/amsel-2024-05-29/

I should have taken a video of that gorgeous bird.