HM [01;04;06]: 10 mile run: 10.31 miles, 00:11:59 average pace, 02:03:32 duration
last run of first training block.
#running
@lyse@lyse.isobeef.org I do wonder how we could build a decentralized way to do this 🤔
user/bmallred/data/2022-08-19-13-25-28.fit: 3.79 miles, 00:11:06 average pace, 00:42:04 duration
@prologic@twtxt.net and others, video call tomorrow/tonight?
Age Milestone Privileges
⌘ Read more
user/bmallred/data/2022-08-18-11-01-04.fit: 3.74 miles, 00:13:19 average pace, 00:49:46 duration
user/bmallred/data/2022-08-17-04-04-18.fit: 8.05 miles, 00:11:35 average pace, 01:33:20 duration
Gen Z
⌘ Read more
user/bmallred/data/2022-08-16-08-53-50.fit: 3.13 miles, 00:10:25 average pace, 00:32:37 duration
⨁ Follow button on their profile page or use the Follow form and enter a Twtxt URL. You may also find other feeds of interest via Feeds. Welcome! 🤗
Freeze, @burglar@txt.sour.is, hand’s up! You’re under arrest!
👋 Hello @burglar@txt.sour.is, welcome to txt.sour.is, a Yarn.social Pod! To get started you may want to check out the pod’s Discover feed to find users to follow and interact with. To follow new users, use the ⨁ Follow button on their profile page or use the Follow form and enter a Twtxt URL. You may also find other feeds of interest via Feeds. Welcome! 🤗
user/bmallred/data/2022-08-15-10-28-34.fit: 5.24 miles, 00:10:35 average pace, 00:55:27 duration
@lyse@lyse.isobeef.org ¯\_(ツ)_/¯ fixed your arm.
@prologic@twtxt.net correct type parameters. 😅
Unreliable Connection
⌘ Read more
Progress! so i have moved into working on aggregates. Which are a grouping of events that replayed on an object set the current state of the object. I came up with this little bit of generic wonder.
type PA[T any] interface {
event.Aggregate
*T
}
// Create uses fn to create a new aggregate and store in db.
func Create[A any, T PA[A]](ctx context.Context, es *EventStore, streamID string, fn func(context.Context, T) error) (agg T, err error) {
ctx, span := logz.Span(ctx)
defer span.End()
agg = new(A)
agg.SetStreamID(streamID)
if err = es.Load(ctx, agg); err != nil {
return
}
if err = event.NotExists(agg); err != nil {
return
}
if err = fn(ctx, agg); err != nil {
return
}
var i uint64
if i, err = es.Save(ctx, agg); err != nil {
return
}
span.AddEvent(fmt.Sprint("wrote events = ", i))
return
}
This lets me do something like this:
a, err := es.Create(ctx, r.es, streamID, func(ctx context.Context, agg *domain.SaltyUser) error {
return agg.OnUserRegister(nick, key)
})
I can tell the function the type being modified and returned using the function argument that is passed in. pretty cray cray.
HM [01;03;06]: 9 mile run: 9.54 miles, 00:11:12 average pace, 01:46:47 duration
casual. end of week 3 of block 1
#running
user/bmallred/data/2022-08-12-12-15-20.fit: 2.82 miles, 00:11:40 average pace, 00:32:51 duration
Coffee Cup Holes
⌘ Read more
@mckinley@twtxt.net Haha, while composing I was wondering two or three times whether I should throw my thoughts in an HTML page instead. But out of utter laziness I discarded that idea. ¯_(ツ)_/¯
@prologic@twtxt.net Error handling especially in Go is very tricky I think. Even though the idea is simple, it’s fairly hard to actually implement and use in a meaningful way in my opinion. All this error wrapping or the lack of it and checking whether some specific error occurred is a mess. errors.As(…) just doesn’t feel natural. errors.Is(…) only just. I mainly avoided it. Yesterday evening I actually researched a bit about that and found this article on errors with Go 1.13. It shed a little bit of light, but I still have a long way to go, I reckon.
We tried several things but haven’t found the holy grail. Currently, we have a mix of different styles, but nothing feels really right. And having plenty of different approaches also doesn’t help, that’s right. I agree, error messages often end up getting wrapped way too much with useless information. We haven’t found a solution yet. We just noticed that it kind of depends on the exact circumstances, sometimes the caller should add more information, sometimes it’s better if the callee already includes what it was supposed to do.
To experiment and get a feel for yesterday’s research results I tried myself on the combined log parser and how to signal three different errors. I’m not happy with it. Any feedback is highly appreciated. The idea is to let the caller check (not implemented yet) whether a specific error occurred. That means I have to define some dedicated errors upfront (ErrInvalidFormat, ErrInvalidStatusCode, ErrInvalidSentBytes) that can be used in the err == ErrInvalidFormat or probably more correct errors.Is(err, ErrInvalidFormat) check at the caller.
All three errors define separate error categories and are created using errors.New(…). But for the invalid status code and invalid sent bytes cases I want to include more detail, the actual invalid number that is. Since these errors are already predefined, I cannot add this dynamic information to them. So I would need to wrap them à la fmt.Errorf("invalid sent bytes '%s': %w", sentBytes, ErrInvalidSentBytes"). Yet, the ErrInvalidSentBytes is wrapped and can be asserted later on using errors.Is(err, ErrInvalidSentBytes), but the big problem is that the message is repeated. I don’t want that!
Having a Python and Java background, exception hierarchies are a well understood concept I’m trying to use here. While typing this long message it occurs to me that this is probably the issue here. Anyways, I thought, I just create a ParseError type, that can hold a custom message and some causing error (one of the three ErrInvalid* above). The custom message is then returned at Error() and the wrapped cause will be matched in Is(…). I then just return a ParseError{fmt.Sprintf("invalid sent bytes '%s'", sentBytes), ErrInvalidSentBytes}, but that looks super weird.
I probably need to scrap the “parent error” ParseError and make all three “suberrors” three dedicated error types implementing Error() string methods where I create a useful error messages. Then the caller probably could just errors.Is(err, InvalidSentBytesError{}). But creating an instance of the InvalidSentBytesError type only to check for such an error category just does feel wrong to me. However, it might be the way to do this. I don’t know. To be tried. Opinions, anyone? Implementing a whole new type is some effort, that I want to avoid.
Alternatively just one ParseError containing an error kind enumeration for InvalidFormat and friends could be used. Also seen that pattern before. But that would then require the much more verbose var parseError ParseError; if errors.As(err, &parseError) && parseError.Kind == InvalidSentBytes { … } or something like that. Far from elegant in my eyes.
user/bmallred/data/2022-08-11-10-04-14.fit: 4.75 miles, 00:10:18 average pace, 00:48:56 duration
user/bmallred/data/2022-08-10-05-08-51.fit: 7.40 miles, 00:12:47 average pace, 01:34:36 duration
Complex Vowels
⌘ Read more
user/bmallred/data/2022-08-09-14-44-31.fit: 2.73 miles, 00:11:22 average pace, 00:31:03 duration
🇨🇺 en llamas 
🇨🇺 en llamas 
user/bmallred/data/2022-08-08-07-55-58.fit: 4.62 miles, 00:11:31 average pace, 00:53:12 duration
Scientific Field Prefixes
⌘ Read more
user/bmallred/data/2022-08-07-13-24-33.fit: 00:45:33 duration
@prologic@twtxt.net can Yarn pods be consumers to other yarn pods?
@abucci@anthony.buc.ci I think so. IndieAuth is what I’m a big fan of. All Yarn pods are IndieAuth providers for example (if there are any concumsers out there, we have to work on a consumer ourselves…)
user/bmallred/data/2022-08-06-07-40-12.fit: 8.09 miles, 00:11:45 average pace, 01:34:59 duration
user/bmallred/data/2022-08-05-14-43-38.fit: 2.85 miles, 00:11:06 average pace, 00:31:35 duration
Asking Scientists Questions
⌘ Read more
Hi, I am playing with making an event sourcing database. Its super alpha but I thought I would share since others are talking about databases and such.
It’s super basic. Using tidwall/wal as the disk backing. The first use case I am playing with is an implementation of msgbus. I can post events to it and read them back in reverse order.

I plan to expand it to handle other event sourcing type things like aggregates and projections.
Find it here: sour-is/ev
@prologic@twtxt.net @movq@www.uninformativ.de @lyse@lyse.isobeef.org
Command palette and commands for managing a graph of notes: https://merveilles.town/@akkartik/108766067153506592
user/bmallred/data/2022-08-04-07-02-18.fit: 4.64 miles, 00:10:30 average pace, 00:48:43 duration
user/bmallred/data/2022-08-03-08-18-09.fit: 6.00 miles, 00:12:51 average pace, 01:17:07 duration
Chemtrails
⌘ Read more
user/bmallred/data/2022-08-02-15-16-21.fit: 2.64 miles, 00:11:30 average pace, 00:30:20 duration
user/bmallred/data/2022-08-01-14-39-33.fit: 4.72 miles, 00:11:13 average pace, 00:52:58 duration
Omnitaur
⌘ Read more
user/bmallred/data/2022-07-30-12-57-50.fit: 00:51:11 duration
user/bmallred/data/2022-07-30-06-32-39.fit: 7.60 miles, 00:10:47 average pace, 01:21:55 duration
user/bmallred/data/2022-07-29-13-32-23.fit: 3.12 miles, 00:12:10 average pace, 00:38:01 duration
Proxy Variable
⌘ Read more
user/bmallred/data/2022-07-28-13-21-28.fit: 4.72 miles, 00:11:48 average pace, 00:55:41 duration