re-encoded all videos to play in HTML5 video tags, and added corresponding support to eureka
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
(cont.)
Just to give some context on some of the components around the code structure.. I wrote this up around an earlier version of aggregate code. This generic bit simplifies things by removing the need of the Crud functions for each aggregate.
Domain ObjectsA domain object can be used as an aggregate by adding the event.AggregateRoot struct and finish implementing event.Aggregate. The AggregateRoot implements logic for adding events after they are either Raised by a command or Appended by the eventstore Load or service ApplyFn methods. It also tracks the uncommitted events that are saved using the eventstore Save method.
type User struct {
Identity string ```json:"identity"`
CreatedAt time.Time
event.AggregateRoot
}
// StreamID for the aggregate when stored or loaded from ES.
func (a *User) StreamID() string {
return "user-" + a.Identity
}
// ApplyEvent to the aggregate state.
func (a *User) ApplyEvent(lis ...event.Event) {
for _, e := range lis {
switch e := e.(type) {
case *UserCreated:
a.Identity = e.Identity
a.CreatedAt = e.EventMeta().CreatedDate
/* ... */
}
}
}
Events
Events are applied to the aggregate. They are defined by adding the event.Meta and implementing the getter/setters for event.Event
type UserCreated struct {
eventMeta event.Meta
Identity string
}
func (c *UserCreated) EventMeta() (m event.Meta) {
if c != nil {
m = c.eventMeta
}
return m
}
func (c *UserCreated) SetEventMeta(m event.Meta) {
if c != nil {
c.eventMeta = m
}
}
Reading Events from EventStore
With a domain object that implements the event.Aggregate the event store client can load events and apply them using the Load(ctx, agg) method.
// GetUser populates an user from event store.
func (rw *User) GetUser(ctx context.Context, userID string) (*domain.User, error) {
user := &domain.User{Identity: userID}
err := rw.es.Load(ctx, user)
if err != nil {
if err != nil {
if errors.Is(err, eventstore.ErrStreamNotFound) {
return user, ErrNotFound
}
return user, err
}
return nil, err
}
return user, err
}
OnX Commands
An OnX command will validate the state of the domain object can have the command performed on it. If it can be applied it raises the event using event.Raise() Otherwise it returns an error.
// OnCreate raises an UserCreated event to create the user.
// Note: The handler will check that the user does not already exsist.
func (a *User) OnCreate(identity string) error {
event.Raise(a, &UserCreated{Identity: identity})
return nil
}
// OnScored will attempt to score a task.
// If the task is not in a Created state it will fail.
func (a *Task) OnScored(taskID string, score int64, attributes Attributes) error {
if a.State != TaskStateCreated {
return fmt.Errorf("task expected created, got %s", a.State)
}
event.Raise(a, &TaskScored{TaskID: taskID, Attributes: attributes, Score: score})
return nil
}
Crud Operations for OnX Commands
The following functions in the aggregate service can be used to perform creation and updating of aggregates. The Update function will ensure the aggregate exists, where the Create is intended for non-existent aggregates. These can probably be combined into one function.
// Create is used when the stream does not yet exist.
func (rw *User) Create(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil && !errors.Is(err, ErrNotFound) {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
// Update is used when the stream already exists.
func (rw *User) Update(
ctx context.Context,
identity string,
fn func(*domain.User) error,
) (*domain.User, error) {
session, err := rw.GetUser(ctx, identity)
if err != nil {
return nil, err
}
if err = fn(session); err != nil {
return nil, err
}
_, err = rw.es.Save(ctx, session)
return session, err
}
I have updated my eventDB to have subscriptions! It now has websockets like msgbus. I have also added a in memory store that can be used along side the disk backed wal.
I have updated my eventDB to have subscriptions! It now has websockets like msgbus. I have also added a in memory store that can be used along side the disk backed wal.
Added some of my latest photos to my timeline :)
Honest Government Ad | US Supreme Court ⌘ Read more
@win0err@kolesnikov.se I agree with @prologic@twtxt.net about the text size. Adding content="width=device-width" to your viewport meta tag will help massively with scaling on different device widths.
Eg. The first screenshot is the current site with a device width of 440px and the second is with the updated viewport meta tag.


Other than that, I like the aesthetic of it 😊 It gives me early-ish internet vibes, which I wasn’t online for (I’m a ‘90s baby) but I’ve seen some pretty early websites.
I just discovered that my phone app (on my personal smartphone) shows me the total call duration of all calls made with the phone so far. A total of about 137.5 hours, which is over five and a half days (!). And that’s just the calls I’ve made using the phone app in the last 22 months. With Telegram and WhatsApp (and my landline phone), I’m sure a few more hours could be added. I’ve often heard the statement that smartphones are hardly used for making calls anymore these days. But apparently I can disprove that. On … ⌘ Read more
@chronolink@chrono.tilde.cafe Replies are not part of the original twtxt format. They were added later as an extension by Yarn.social: https://dev.twtxt.net/doc/twtsubjectextension.html (only the section “Machine-Parsable Conversation Grouping” is used these days)
Honest Government Ads | Season 3 Launch 🎉 ⌘ Read more
GitHub enables the development of functional safety applications by adding support for coding standards AUTOSAR C++ and CERT C++
GitHub is excited to announce the release of CodeQL queries that implement the standards CERT C++ and AUTOSAR C++. These queries can aid developers looking to demonstrate ISO 26262 Part 6 process compliance. ⌘ Read more
All this time spent being grumpy about how adding my Now updates directly into the html page is uncomfortable, and it just occurred to me I can chug it into a text file and use cat.
I started adding a list of books that changed my life to my tilde at http://tilde.club/~melyanna/library/
Honest Government Ad | 1 Week Left! ⌘ Read more
Honest Government Ad | 2022 Election (Season 2 finale) ⌘ Read more
I added pointlessArgument: 'is a taco a sandwich' to a pile-of-arguments object today
Honest Government Ad | Carbon Credits & Offsets ⌘ Read more
Honest Government Ad | We need to talk about the floods | with Sue Higginson ⌘ Read more
Alright, check this out. I just kinda completed today’s project of converting a jeans into a saw bag. It’s not fully done, the side seams on the flap need some more hand sewing, that’s for sure. No, I don’t have a sewing machine. Yet?
At first I wanted to put in the saw on the short side, but that would have made for more sewing work and increased material consumption. As a Swabian my genes force me to be very thrifty. Slipping in on the long side had the benefit of using the bottom trouser leg without any modification at all. The leg tapers slightly and gets wider and wider the more up you go. At the bottom it’s not as extreme as at the top.
The bag is made of two layers of cloth for extra durability. The double layers help to hide the inner two metal snap fastener counter parts, so the saw blade doesn’t get scratched. Not a big concern, but why not doing it, literally no added efforts were needed. Also I reckon it cuts off the metal on metal clinking sounds.
The only downside I noticed right after I pressed in the receiving ends of the snap fasteners is that the flap overhangs the bag by quite a lot. I fear that’s not really user-friendly. Oh well. Maybe I will fold it shorter and sew it on. Let’s see. The main purpose is to keep the folding saw closed, it only locks in two open positions.
Two buttons would have done the trick, with three I went a bit overkill. In fact the one in the middle is nearly sufficient. Not quite, but very close. But overkill is a bit my motto. The sides making up the bag are sewed together with like five stitch rows. As said in the introduction, the flap on the hand needs some more love.
Oh, and if I had made it in a vertical orientation I would have had the bonus of adding a belt loop and carrying it right along me. In the horizontal layout that’s not possible at all. The jeans cloth is too flimsy, the saw will immediately fall out if I open the middle button. It’s not ridgid enough. Anyways, I call it a success in my books so far. Definitely had some fun.
Honest Government Ad | The Floods 🌊 ⌘ Read more
Conservative leadership race turns nasty between Poilievre and Brown
Video: C Programming on System 6 - Talking to the Modem
Starting work on adding a serial module to join the console and telnet inputs, to allow calls through a modem. I got stuck for a while trying to figure out why writes to the serial port would hang the machine. ⌘ Read more
Honest Government Ad | United Australia Party ⌘ Read more
Here’s a preview of some themes I’m adding to https://mkws.sh https://files.mills.io/download/plain.jfif, https://files.mills.io/download/mono.jfif !
Made a bunch of pretty much invisible changes to my twtxt.txt file 😋 Pretty much just added an avatar and description and stuff.
New year, new habits?!
Colin’s post yesterday inspired me to install the Loop Habit Tracker app. How did I not know about this app yet? Free, no ads, and even open source! ⌘ Read more
I have uBlockOrigin on desktop and https://vancedapp.com/ on android. I never see ads on YouTube.
On SmartTV however this would be a nice addition.
I have uBlockOrigin on desktop and https://vancedapp.com/ on android. I never see ads on YouTube.
On SmartTV however this would be a nice addition.
You’re right @ullarah@txt.quisquiliae.com I just watched Australia Post Outrage: Did She Need To Go? and I do believe I’ll start adding this to my “watchlist” – I don’t use Youtube specifically (because privacy eroding garbage); but the content this guy produces is awesome! 👌
Scotty from marketing really needs to be fired! Can we even fire Prime Ministers besides calling an election? 🤔 The more you dig into our #Australian #Government the more you realize just how fucking corrupt they all are and have been over so many years. How?! 🤦
Honest Government Ad | Hung Parliament ⌘ Read more
Blue-teaming for Exiv2: adding custom CodeQL queries to code scanning
The Exiv2 team tightened our security by enabling GitHub’s code scanning feature and adding custom queries tailored to the Exiv2 code base. ⌘ Read more
Honest Government Ad | Net Zero by 2050 ⌘ Read more
Honest Government Ad | COP26 Climate Summit ⌘ Read more
Telegram Ads
So Telegram now has ads. But unlike the ads from Google, Facebook or Apple, the ads are not personalized and much more privacy friendly. The ads simply consist of a maximum 160-character message with no external links and are displayed only in large public channels. ⌘ Read more
My nutritional supplements aim should be:
- 1 or 1.5 cups of lentils (or any beans you might like better).
- 2 or 2.5 cups of bitter greens.
- 1 cup of your favourite protein (or an egg), grilled, or fried with a little of olive oil.
- 1 or 2 tomatoes, or a handful if of the cherry type.
- No added sugars. If it is sweet, make it have fibre.
- No added salt (or very little and ionised), as salt is everywhere.
Related, I tried wild rice for the first time yesterday. It was different, in a good way.
@movq@www.uninformativ.de Yup. Added all the language ones, and bam, working like a charm!
It’s Tuesday, but somehow I have a Thursday kind of feeling… Whatever. I’m following an online auction for a couple of PDAs. The starting price is more than I’d be willing to pay, but there isn’t a single bidder yet. I hope that last, because the seller will put the ad out for a lower price if it does!
@quark@twtxt.netbros.com Answering to myself: it doesn’t. @movq@www.uninformativ.de, would that be something that it could be added?
@quark@twtxt.netbros.com I have removed the cron job, and added jenny -f to the small script that starts mutt with the .muttrc-jenny file. That way when I open, it refresh the feed before. Let’s see how it goes.
GitHub Advisory Database now powers npm audit
Today, we’re adding a proxy on top of the GitHub Advisory Database that speaks the `npm audit` protocol. This means that every version of the npm CLI that supports security audits is now talking directly to the GitHub Advisory Database. ⌘ Read more
Honest Government Ad | AUKUS ⌘ Read more
GitHub Enterprise Server 3.2 brings new color modes and added security capabilities
GitHub Enterprise Server 3.2 is available today as a release candidate. With this release, we’re shipping over 70 new features and changes to improve the developer experience and deliver new security capabilities for our customers. ⌘ Read more
Honest Government Ad | Carbon Capture and Storage ⌘ Read more
2021 Transparency Report: January to June
We’re reporting on a six-month period rather than annually to increase our level of transparency. For this report, we’ve added more granularity to our 2020 stats. ⌘ Read more
Bringing back old-school web pins and buttons
Back in the not-quite-as-bad-old-days (at least as far back as the 90’s), every good website had a small “ad” gif that fans of the site could use as a colorful link. These are called “buttons” or sometimes “pins.”
You can see sites that collect these internet artifacts (both the good ones and boring ones) here and here.
Most people would have **do … ⌘ Read more
Honest Government Ad | Hotel Quarantine ⌘ Read more
Adding support for cross-cluster associations to Rails 7 ⌘ Read more…
added shrine to Artisans who inspire me
finished Sandworms of Dune and added some photos to the Earth shrine
No, I’m still doing them manually. 🤣🤦🏻 But I do think they are a good idea and will be adding them, I just haven’t gotten around to finding a compatible implementation of the hash yet.
Added to the fun.
Added to the fun.
Honest Government Ad | We Make Everything Good Sh!t ⌘ Read more
new recipe added to the !food page: !brownies.
added a shrine to Earth, updated Wheels shrine
added a !projects page. it’s dynamically generated :)
added nilFM twtxt feed
Honest Government Ads | 5 Year Special! ⌘ Read more
The Problems with Utilitarianism
I originally wrote this essay in 2014 or 2015 in a Chinese buffet in Athens, Georgia. I’ve changed some of it and am re-adding it here. I talk about the issues with Utilitarianism and a bad book by Sam Harris.
At a dumb intuitive level, the “ethical” idea of Utilitarianism in principle gets pretty close to what most people reflexively want from social-political affairs: the greatest good for the greatest number of people—who … ⌘ Read more
Honest Government Ad | Electric Vehicles ⌘ Read more
My blog system now has tagging (all pure POSIX shell of course)
This isn’t live on the old blog system’s Github, but partially inspired by by Based Cooking’s tag system which is based on blogit, I’ve added in the feature to tag articles.
I’ve been wanting to write more articles and informational pages on my website, but doing that with no organization is somewhat … ⌘ Read more
I like and use the Brave Browser.It’s a free and open source browser with features like:
- Ad-blocking by default.
- Tracker-blocking by default.
- Anti-fingerprinting mechanisms to prevent you from being monitored.
- Built-in Tor windows.
- Run by a based Christian and not furry leftists.
As far as I’m concerned, Brave is indisputably the best general-purpose browser out there.There are other okay brows … ⌘ Read more
YouTube Channel Deletion (updated)
For info, I’ve added a list of the striked videos so you can see how innocuous they are. ⌘ Read more
Honest Government Ad | Australian Values ⌘ Read more
Antivax, How are they funded? Investigating ad trackers with Gephi and the DMI Tracker Tracker tool - First Draft ⌘ Read more…
@niplav@niplav.github.io I wouldn’t disagree with your characterization of people who’re interested in radical life extension, but their messaging, generally, seems to not mention “adding life to your years” at all. “Live to be 150” doesn’t sound all that great if you’re going to have 15 years of being in your 80s, so to speak.
added some more words to the !LIL page.
@(frogorbits.com) “@niplav Seems like most of the (radical) life extension people are interested in adding years to their lives, but agnostic about adding life to their years. “Be old longer” doesn’t appeal to a lot of people.” -> I disagree, the people who i know that are interested in life extension look to me more engaged in life than the ones who are not (though that hinges on definitions of ”adding life to their years”). i agree that “adding life to your years” is underappreciated, though.
added a new algo to sndkit @!(sndkitref “scale”)!@.
@niplav@niplav.github.io Seems like most of the (radical) life extension people are interested in adding years to their lives, but agnostic about adding life to their years. “Be old longer” doesn’t appeal to a lot of people.
Honest Government Ad | News Media Bargaining Code ⌘ Read more
added biramp to sndkit: @!(sndkitref “biramp”)!@.
added recipe I use for brown sugar cinammon poptarts: !poptarts #food #breakfast #baking
@prologic@twtxt.net the meta info on the top I added manually. it’s following what I have seen from some other twtxt feeds. the new parser will read them.
@prologic@twtxt.net the meta info on the top I added manually. it’s following what I have seen from some other twtxt feeds. the new parser will read them.
@xuu@txt.sour.is Btw… I noticed your pod has some changed I’m not familiar with, for example you seem to have added metadata to the top of feeds. Can you enumerate the improvements/changes you’ve made and possibly let’s discuss contributing them back upstream? :D
@prologic@twtxt.net in theory shouldn’t need to let users add feeds.. if they get mentioned by a tracked feed they will get added automagically. on a pod it would just need to scan the twtxt feed to know about everyone.
@prologic@twtxt.net in theory shouldn’t need to let users add feeds.. if they get mentioned by a tracked feed they will get added automagically. on a pod it would just need to scan the twtxt feed to know about everyone.
PeerTube v3 is now live with Live Streaming abilities
PeerTube has recently released version 3.0.0, which has added many things, including the ability to livestream. I’ve already updated by PeerTube instance to version 3 (it is linked from this RSS entry), but the link is just videos.lukesmith.xyz .
I’m not sure if I’ll end up immediately using the livestream ability, but it is certainly nice to have a non-YouTube option which is, in fact, self-hosted.
Aside from that, I strong recommend you … ⌘ Read more
lots of links added to overview page on monolith wiki: @!(monolithref “overview”)!@.
Honest Government Ads | Behind the scenes 2020 ⌘ Read more
@prologic@twtxt.netdd ooh I am adding that to my test suite
@prologic@twtxt.netdd ooh I am adding that to my test suite
@prologic@twtxt.net Testing if this will be added to the thread just adding the hashtag. #utwnv7q
@prologic@twtxt.net Testing if this will be added to the thread just adding the hashtag. #utwnv7q
added a !meta page. this proof of concept integrates with the weewiki !zettelkasten I am developing to produce something similar to this !feed.
@prologic@twtxt.net def would be a wider discussion on preventing the pod from adding its own key to a users device list. Or using device keys to authenticate instead of user/pass.
@prologic@twtxt.net def would be a wider discussion on preventing the pod from adding its own key to a users device list. Or using device keys to authenticate instead of user/pass.
Honest Government Ad | Kyoto Carryover Credits ⌘ Read more
added some pages on #permissive #publicdomain licenses that I often reach for: !CC0 and !unlicense.
@prologic@twtxt.net an added benefit of the avatar: would be the user could put their gravatar/libravatar image url like https://key.sour.is/avatar/01bc6186d015218c23dec55447e502e669ca4c61c7566dfcaa1cac256108dff0
@prologic@twtxt.net an added benefit of the avatar: would be the user could put their gravatar/libravatar image url like https://key.sour.is/avatar/01bc6186d015218c23dec55447e502e669ca4c61c7566dfcaa1cac256108dff0
Ad Watch by Persuasion Lab - Political ad spending Belgium Dashboard ⌘ https://ad.watch/country/belgium.html
Video: C Programming on System 6 - Adding a GUI to diff(1) ⌘ Read more…
added an initial !bitwrite page #updates
added channels page to !monolith wiki: [[/proj/monolith/wiki/channels]]. #updates
added a few notes on woven program output on the !monolith wiki page #updates
added @!(sndkitref “bezier”)!@ to !sndkit today. coupled with @!(sndkitref “oscf”)!@, it is capable of making some really weird wet FM-y sounds. Me like! #updates #sndkit