@xuu@txt.sour.is proof of stake = people with money get more money. It accelerates the wealth inequality problems that are already plaguing us. Crypto has even worse wealth inequality than fiat currency systems, which is 100% predictable.
-1 for the negative on environment all that electricity uses. Still waiting on proof of stake.
It is also too overrun with Tech Bros scamming people to get rich quick.
It was a fun ride back when I first bought in. But I have since cached out for my lambos and such.
-1 for the negative on environment all that electricity uses. Still waiting on proof of stake.
It is also too overrun with Tech Bros scamming people to get rich quick.
It was a fun ride back when I first bought in. But I have since cached out for my lambos and such.
One year ago, I started using AdGuard Home instead of Pi-Hole to filter DNS requests and block ads and tracking. Yesterday, I switched to NextDNS instead. NextDNS has mostly the same features, but is hosted in the “cloud” and I have one less self-hosted service to care about. AdGuard Home is awesome, but NextDNS seems to be working great as well and also integrates with Tailscale easily. ⌘ Read more
How to Use the Postgres Docker Official Image
Check out our guide on how to use the Postgres Docker Official Image, including options for customization and data storage tips. ⌘ Read more
FAQ: Lunduke Journal Lifetime Subscription
Since the Lifetime Subscription option was launched, for The Lunduke Journal, there have been a few common questions people have had. To make things easier for all of us, here are some of the most Frequently Asked Questions about Lifetime Subscriptions. In no particular order. ⌘ Read more
The XMPP Standards Foundation: The XMPP Newsletter September 2022
Welcome to the XMPP Newsletter, great to have you here again! This issue covers the month of September 2022.
Like this newsletter, many projects and their efforts in the XMPP community are a result of people’s voluntary work. If you are happy with the services and software you may be using, especially throughout the current situation, please consider saying thanks or help these projects! Interested in supporting the Newsletter team? Read mor … ⌘ Read more
Tigase Blog: Tigase XMPP Libraries
Our software philosophyActually nothing new and nothing surprising here. We want to have as much of a reusable code as possible. And this
reusable code should have a simple but powerful API to be useful for quickly creating software.
That’s it.
And this is how we design and develop our XMPP libraries. Check them out.
Documentation to all our projects is available online and sample codes? Take a look at our XMPP Chat apps which are
open source too. ⌘ Read more
**RT by @mind_booster: 85% of surveyed teachers and educators use online digital collections while conducting educational activities
There are so many opportunities for cultural institutions to cooperate with teachers and educators🚀
Find out more in our new report 👉🏻 http://centrumcyfrowe.pl/en/open-glam-2022**
85% of surveyed teachers and educators use online digital collections while conducting educational activities
There are so many opportunities for cultural institutions to cooperate with teachers and … ⌘ Read more
September Extensions Roundup: Test APIs, Use Oracle SQLcl, and More
Find out what’s new this month in the Docker Extension Marketplace! Access InterSystems, test APIs, use Oracle SQLcl, and backup/share volumes — right from Docker Desktop. ⌘ Read more
80,000 hours podcast but it’s only Rob Wiblin speaking. Useful for voice synthesis.
Decided to use FLTK crate, that one is easy to get set up, works well.
Now I have to figure out how to make a class that holds the gui elements I need.
I want to parse the yarn status file, then show the statuses, then once that works I’ll make it fetch it online etc. Will take some time, but I feel a bit more motivated (for now) to do this in rust.
Clarifying Misconceptions About Web3 and Its Relevance With Docker
This blog is the first in a two-part series. We’ll talk about the challenges of defining Web3 plus some interesting connections between Web3 and Docker. Part two will highlight technical solutions and demonstrate how to use Docker and Web3 together. We’ll build upon the presentation, “Docker and Web 3.0 — Using Docker to Utilize Decentralized […] ⌘ Read more
Paul Schaub: Using Pushdown Automata to verify Packet Sequences
As a software developer, most of my work day is spent working practically by coding and hacking away. Recently though I stumbled across an interesting problem which required another, more theoretical approach;
An OpenPGP message contains of a sequence of packets. There are signatures, encrypted data packets and their accompanying encrypted session keys, compressed data and literal data, the latter being the packet … ⌘ Read more
8 things you didn’t know you could do with GitHub Copilot
Developers all over the world are using GitHub Copilot to help speed up their development and increase developer productivity. With GitHub Copilot available to developers everywhere, we’ve found some fun and useful examples of how developers can use GitHub Copilot for things you may not be thinking about. ⌘ Read more
GoToSocial seems like a promising alternative to Mastodon. It’s written in Go (👍 in my opinion), lightweight and pretty good documented so far. It’s still “alpha software” but seems to make great progress. In the past, I self hosted a microblog.pub instance and then after some time without any Fediverse profile other than my blog, which has ActivityPub support as well, signed up at Fosstodon to be able to reply to blog comments from the Fediverse. I already set up an instace of GTS, but will probably wait to use it … ⌘ Read more
“DOS Week” subscription sale
Huge, bonkers discounts. Take advantage of the deal and join us for “DOS Week”! ⌘ Read more
Gear-up and unlock the newest GitHub Global Campus features
Calling all students and teachers! With semester change coming soon, now is the time to start using the latest features within GitHub Education and Global Campus! ⌘ Read more
wsl-vpnkit: Internet for WSL2 distros behind a VPN
I’m still alive. 👋 Today, at work, I discovered a nice little tool for WSL2. On my work laptop I need to use Cisco AnyConnect to connect to the corporate network. Unfortunately this blocks Internet access in Windows Subsystem for Linux VMs (at least in the Ubuntu VM, I tried to use for some Docker stuff). I tried a lot of different hacks and workarounds, but none worked. Until I found wsl-vpnkit. It just works. 😄 ⌘ Read more
I used a dumb phone for 30 days ⌘ Read more
Arnaud Joset: Updates: chatty server and HTTPAuthentificationOverXMPP
It’s been a long time since I updated this blog. It will be a short update post about two projects.
The first is chatty_server, a small XMPP bot I use to interact with my server. It allows me to get information about the CPU load, traffic, weather etc.
It also has a small feature to get reminder messages. There was a bug that allowed anyone to spam reminders. Anybody can add the bot to their rooster and could create random reminders t … ⌘ Read more
Monal IM: Monal IM – project moved
We recently started to migrate the App from Anu Pokharel‘s Apple account to Thilo Molitor‘s Apple account.
Aspart of this transition we also deployed some new push servers to not let an old retired developer pay for the infrastructure needed for Monal.
Coming along with this transition from the old developer team to the new one is our new clean website at https://monal-im.org/. From now on, this blog will not be used for Monal anymore.
**Many t … ⌘ Read more
SCA vs SAST: what are they and which one is right for you?
We’re taking a look at two commonly-used security tools and detailing how they can help secure your projects. ⌘ Read more
Dino: Stateless File Sharing: Async, Metadata with Thumbnails and some UI
AsyncAsynchronous programming is a neat tool, until you work with a foreign project in a foreign language using it.
As a messenger, Dino uses lots of asynchronous code, not always though.
Usually my progress wasn’t interfered by such instances, but sometimes I had to work around it.
Async in Vala
No surprises here.
Functions are annotated with async, and yield expressions that are asyn … ⌘ Read more
RT by @mind_booster: In 2004, my wife came home from the Game Developers Conference with a wild story. A presenter claimed to have a sweatshop on the US/Mexican border where low-waged workers did repetitive tasks in Everquest to amass virtual gold, which was sold on Ebay to lazier, richer players 1/
In 2004, my wife came home from the Game Developers Conference with a wild story. A presenter claimed to have a sweatshop on the US/Mexican border where low-waged workers did repetitive tasks in Everquest to amass v … ⌘ Read more
How to Use the Alpine Docker Official Image
Learn how to Dockerize Alpine for your next application or server with our guide on how to use the Alpine Docker Official Image. ⌘ Read more
Research: quantifying GitHub Copilot’s impact on developer productivity and happiness
When the GitHub Copilot Technical Preview launched just over one year ago, we wanted to know one thing: Is this tool helping developers? Our research, using a combination of surveys and experiments, led us to expected and unexpected answers. ⌘ Read more
@akoizumi@social.kyoko-project.wer.ee I don’t really like the way openbsd does things and use Debian on all my servers. But on the desktop side I like it but don’t use it
The XMPP Standards Foundation: The XMPP Newsletter August 2022
Welcome to the XMPP Newsletter, great to have you here again! This issue covers the month of August 2022.
Like this newsletter, many projects and their efforts in the XMPP community are a result of people’s voluntary work. If you are happy with the services and software you may be using, especially throughout the current situation, please consider saying thanks or help these projects! Interested in supporting the Newsletter team? Read more at the … ⌘ Read more
Join us for OctogatosConf 2022
Live on September 15, 2022, with talks by industry experts in Spanish, Portuguese, and English, on topics including software development, security, technical project management, community, open source, professional development and best practices. ⌘ Read more
@prologic@twtxt.net Yeah its never going to change but its an option to use UTC
@prologic@twtxt.net That is confusing and no one will understand how to use it. But I did not even know UTC means Coordinated Universal Time. We need to make a revolution to get rid of timezones on the internet and just use UTC
@mckinley@twtxt.net We need to make something like computer time or something like that so people using a computer can say like lets have a chat thursday at 7:00 and no timezone things.
@ocdtrekkie@twtxt.net That is cool that there is no tpic. Its not like people on these open platforms have to use linux or some free and open os. Anyone can use whatever they want to. Yarn is just a web ui for twtxt and the os does not matter. I can’t say on for long time at midnight and I left before you started.
@movq@www.uninformativ.de Yeah in the US the clocks did not change yet. It switches in Novemeber.
@ocdtrekkie@twtxt.net I could not join because the chat was at 12:30 or 1:00 am for me. Well if I do end up joining sometime I don’t use windows and have not used windows in months. Don’t have anything to say about windows 11 because I never used it and have not used windows in a few months or more.
@jason@jasonsanta.xyz / @movq@www.uninformativ.de Help me debug something I just observed here… @jason@jasonsanta.xyz posted a Twt (https://twtxt.net/twt/4cgtisa) with raw line of (from his feed):
2022-09-03T03:40:19Z (#ohihfkq) @<maya https://maya.land/assets/twtxt.txt> you got starlink?
Basically replying to “something” that hashed to #ohihfkq
However #ohihfkq appears nowhere that I can find. I know this can sometimes happen due to edits, or deletes, so just curious to see what happened here. Also @jason@jasonsanta.xyz, @maya@maya.land as far as many of us that have been using Twtxt/Yarn over the years have come to understand that she is basically a 1-way poster, posts to Mastodon and mirrors her posts to a Twtxt feed, but never responds to anyone or anything 😅 Just FYI 🤗
@prologic@twtxt.net I think now I know what forked threads are and figured out how to use them but i don’t really know
@prologic@twtxt.net I don’t think I have used forked threads before
@prologic@twtxt.net Yeah I never used it before
How to Colorize Black & White Pictures With OpenVINO™ on Ubuntu Containers
Ever wanted to learn how to colorize monochrome pictures? You can use OpenVINO on Ubuntu containers to do just that! Learn more from our friends over at Ubuntu. ⌘ Read more
Integrated Terminal for Running Containers, Extended Integration with Containerd, and More in Docker Desktop 4.12
Docker Desktop 4.12 is now live! This release brings some key quality-of-life improvements to the Docker Dashboard. We’ve also made some changes to our container image management and added it as an experimental feature. Finally, we’ve made it easier to find useful Extensions. Let’s dive in. Execute commands in a runn … ⌘ Read more
Ignite Realtime Blog: Openfire ThreadDump plugin 1.1.0 released
Earlier today, we have released version 1.1.0 of the Openfire Thread Dump plugin. This plugin uses various evaluators to trigger the creation of a Java thread dump. These thread dumps provide valuable information that is typically used when analyzing issues within Openfire’s implementation.
In the new version of the plugin, two new evaluators have been added: one that looks at the usage pattern of Openfire’s TaskEngin … ⌘ Read more
Git’s Database Internals III: File History Queries
Git’s file history queries use specialized algorithms that are tailored to common developer behavior. Level up your history spelunking skills by learning how different history modes behave and which ones to use when you need them. ⌘ Read more
How to Build and Run Next.js Applications with Docker, Compose, & NGINX
At DockerCon 2022, Kathleen Juell, a Full Stack Engineer at Sourcegraph, shared some tips for combining Next.js, Docker, and NGINX to serve static content. With nearly 400 million active websites today, efficient content delivery is key to attracting new web application users. In some cases, using Next.js can boost deployment efficiency, accelerate time to market, […] ⌘ Read more
@movq@uninformativ.de There might not even be any benefit to moving that to yarn.social. Besides the yarn site should promote using yarn not twtxt even though there is a little bit of information on the site.
@prologic@twtxt.net Yeah I don’t even know how to use them once I added myself to the registries. The jarn search engine is similar to the registries thing but its easier to search and find things from. Also I assume its easier to use it in the yarn pods and whatever elese to get new posts. I would always like to see yarn work with regular twtxt because there is advantges to plain twtxt.
@prologic@twtxt.net I do think the post about how to setup jenny + mutt over on the uninformativ.de blog is still a great post. I used that post to see the steps to set it up and it works fine. Though I can write some blog post with some more documentation for things like auto publishing. The big issue with plain twtxt is that I would have not seen your post unless I looked on twtxt.net when I was looking at yarn a little bit more. Twtxt does overcome the issue by introducing the registry but I can’t figure out any way to use them for Jenny and almost no one uses them in the first place. So I can’t see anyones replies or mentions unless I am following them. Yarn does overcome the issue by friends of friends as you would know as the creator of yarn.
How to Set Up Your Local Node.js Development Environment Using Docker
Learn how to set up a local Node.js development environment using Docker with this step-by-step guide! ⌘ Read more
JMP: Signup with Cheogram Android
Welcome to JMP.chat! If you are looking for a simple guide on how to sign up for JMP, then you have come to the right place! We will be keeping this guide up-to-date if there is ever a change in how to sign up.
We will first start with signing up from within your Jabber chat application on mobile, where you will never need to leave the client to get set up. I will be using the freedomware Android client Cheogram to do this signup. To star … ⌘ Read more
JMP: Signup with Cheogram Android
Welcome to JMP.chat! If you are looking for a simple guide on how to sign up for JMP, then you have come to the right place! We will be keeping this guide up-to-date if there is ever a change in how to sign up.
We will first start with signing up from within your Jabber chat application on mobile, where you will never need to leave the client to get set up. I will be using the freedomware Android client Cheogram to do this signup. To star … ⌘ Read more
JMP: Signup with Cheogram Android
Welcome to JMP.chat! If you are looking for a simple guide on how to sign up for JMP, then you have come to the right place! We will be keeping this guide up-to-date if there is ever a change in how to sign up.
We will first start with signing up from within your Jabber chat application on mobile, where you will never need to leave the client to get set up. I will be using the freedomware Android client Cheogram to do this signup. To star … ⌘ Read more
Git’s database internals I: packed object store
This blog series will examine Git’s internals to help make your engineering system more efficient. Part I discusses how Git stores its data in packfiles using custom compression techniques. ⌘ Read more
@abucci@anthony.buc.ci Its not better than a Cat5e. I have had two versions of the device. The old ones were only 200Mbps i didn’t have the MAC issue but its like using an old 10baseT. The newer model can support 1Gbps on each port for a total bandwidth of 2Gbps.. i typically would see 400-500Mbps from my Wifi6 router. I am not sure if it was some type of internal timeout or being confused by switching between different wifi access points and seeing the mac on different sides.
Right now I have my wifi connected directly with a cat6e this gets me just under my providers 1.3G downlink. the only thing faster is plugging in directly.
MoCA is a good option, they have 2.5G models in the same price range as the 1G Powerline models BUT, only if you have the coax in wall already.. which puts you in the same spot if you don’t. You are for sure going to have an outlet in every room of the house by code.
@abucci@anthony.buc.ci Its not better than a Cat5e. I have had two versions of the device. The old ones were only 200Mbps i didn’t have the MAC issue but its like using an old 10baseT. The newer model can support 1Gbps on each port for a total bandwidth of 2Gbps.. i typically would see 400-500Mbps from my Wifi6 router. I am not sure if it was some type of internal timeout or being confused by switching between different wifi access points and seeing the mac on different sides.
Right now I have my wifi connected directly with a cat6e this gets me just under my providers 1.3G downlink. the only thing faster is plugging in directly.
MoCA is a good option, they have 2.5G models in the same price range as the 1G Powerline models BUT, only if you have the coax in wall already.. which puts you in the same spot if you don’t. You are for sure going to have an outlet in every room of the house by code.
I use encrypted email as well. But not frequently, since almost noone does the same.
I maintain keys for my email addresses.. but like most in this thread i almost never receive encrypted emails.. other than the BTC exchange i use that sends automated mail encrypted.
I maintain keys for my email addresses.. but like most in this thread i almost never receive encrypted emails.. other than the BTC exchange i use that sends automated mail encrypted.
I use IP over Alternating Current at home. The only issue is the bridges forget device MACs sometimes and I get weird states where I can ping a deviceA and the the internet from deviceB. But deviceA can only ping device B even though they are on the same subnet and default gateway.
I use IP over Alternating Current at home. The only issue is the bridges forget device MACs sometimes and I get weird states where I can ping a deviceA and the the internet from deviceB. But deviceA can only ping device B even though they are on the same subnet and default gateway.
Does anyone of you use PGP encrypted mail, or any kind or email encryption? Why? Why not?
How to Develop and Deploy a Customer Churn Prediction Model Using Python, Streamlit, and Docker
Customer churn is a million-dollar problem for businesses today. The SaaS market is becoming increasingly saturated, and customers can choose from plenty of providers. Retention and nurturing are challenging. Online businesses view customers as churn when they stop purchasing goods and services. Customer churn can depend on industry-specific factors, y … ⌘ Read more
Introducing Trilogy: a new database adapter for Ruby on Rails
We’ve open sourced Trilogy, the database adapter we use to connect Ruby on Rails to MySQL-compatible database servers. ⌘ Read more
Erlang Solutions: Implementing Go Fish to Learn Elixir
A walkthrough of how we implemented GoFish as a way of learning Elixir and the concepts of the BEAM and OTP.
In this article, we will outline our initial design and implementation of the card game Go Fish in Elixir using raw processes, and then describe how we were motivated to re-implement the project using the GenServer module instead. The first step is to agree upon the rules of the game, then describe the domain mode … ⌘ Read more
Erlang Solutions: How Can Technology Answer the Questions Still Unanswered in FinTech?
Leaders in the fintech industry joined us to discuss how technology can answer the remaining questions in fintech. They explored key technologies shaping the sector that could also have an impact on society as a whole. Join our panel moderated by Andrew Vorster (Innovation Catalyst) featuring Jacky Uys (Mambu … ⌘ Read more
** Miscellaneous this and that **
Since my brain injury (which I’ve since learned can be called an“ABI” or“acquired brain injury”) I’ve noticed that I have trouble focusing on programming tasks; I’m able to do what I need to do for work and family but, when it comes time for hobby projects I’m just gloop. Totally oozy.
Because of that I’ve been drawn to do more reading and game playing, but also still wanna code…I’ve found that it is easier to use more“batteries included” kinda languages, namely scheme, over what I’d … ⌘ Read more
@prologic@twtxt.net I think we could use deltachats new decentralising app format for it: https://delta.chat/en/2022-06-14-webxdcintro
testing twtxt using jenny
I should have attended the Homebrew Website Club London / Europe in June, after all they talked about maps, a topic I have some experience with. James uses Leaflet to create maps with his visited coffee shops. 👍 ⌘ Read more
I should have attended the Homebrew Website Club London / Europe in June, after all they talked about maps, a topic I have some experience with. James uses Leaflet to create maps with his visited coffee shops. 👍 ⌘ Read more
GitHub Discussions is now available on GitHub Enterprise Server
As part of GitHub Enterprise Server 3.6, enterprise customers will now be able to use GitHub Discussions. ⌘ Read more
👋 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! 🤗
👋 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! 🤗
(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
}
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.
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.
by which the future life expectancy of some non-perishable things, like a technology or an idea, is proportional to their current age. Thus, the Lindy effect proposes the longer a period something has survived to exist or be used in the present, the longer its remaining life expectancy. The disproportionate influence of early tech decisions — brandur.org
Tailscale SSH
I finally got around to using Tailscale SSH. I’ve been using Tailscale for over a year to access my servers via SSH (my VPS is even available via Tailscale only), but I haven’t used the new Tailscale SSH feature yet. ⌘ Read more
With respect to logging.. oh man.. it really depends on the environment you are working in.. development? log everything! and use a jeager open trace for the super gnarly places. So you can see whats going on while building. But, for production? metrics are king. I don’t want to sift through thousands of lines but have a measure that can tell me the health of the service.
With respect to logging.. oh man.. it really depends on the environment you are working in.. development? log everything! and use a jeager open trace for the super gnarly places. So you can see whats going on while building. But, for production? metrics are king. I don’t want to sift through thousands of lines but have a measure that can tell me the health of the service.
@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.
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.
GitHub Pages now uses Actions by default
As GitHub Pages, home to 16 million websites, approaches its 15th anniversary, we’re excited to announce that all sites now build and deploy with GitHub Actions. ⌘ Read more
The US put tornadocash on sanction list. Deleted github accounts and source. Since North Korea used it to launder stolen crypto.
And people are surprised that it happened? Github is and never have been a safe place to store code. Tor/i2p is much more safer places to host code. But I understand why people use github, I do so as well for public project, but I also selfhost my other things
I did a take home software engineering test for a company recently, unfortunately I was really sick (have finally recovered) at the time 😢 I was also at the same time interviewing for an SRE position (as well as Software Engineering).
Got the results of my take-home today and whilst there was some good feedback, man the criticisms of my work were harsh. I’m strictly not allowed to share the work I did for this take-home test, and I really can only agree with the “no unit tests” piece of the feedback, I could have done better there, but I was time pressured, sick and ran out of steam. I was using a lot of libraires to do the work so in the end found it difficult to actually think about a proper set of “Unit Tests”. I did write one (in shell) but I guess it wasn’t seen?
The other points were on my report and future work. Not detailed enough I guess? Hmmm 🤔
Am I really this bad? Does my code suck? 🤔 Have I completely lost touch with software engineering? 🤦♂️
I started working on plugins for GoBlog using a Go module I recently discovered: yaegi. It still feels like magic, because Go is typically a compiled language and yaegi makes it dynamic by embedding an interpreter. Is this overkill for GoBlog or does this possibly enable flexibility like WordPress plugins? ⌘ Read more
Release Radar · July 2022 Edition
While some of us have been wrapping up the financial year, and enjoying vacation time, others have been hard at work shipping open source projects and releases. These projects include everything from world-changing technology to developer tooling, and weekend hobbies. Here are some of the open source projects that released major version updates this July. […] ⌘ 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
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
from now on, when talking about fractions, i will only use the terms “upper number” and “lower number”. those both have fewer syllables AND they’re vastly easier to understand. Thank you for coming to my TED talk.
Destroying Politicians using A.I ⌘ Read more
The XMPP Standards Foundation: The XMPP Newsletter July 2022
Welcome to the XMPP Newsletter, great to have you here again! This issue covers the month of July 2022.
Like this newsletter, many projects and their efforts in the XMPP community are a result of people’s voluntary work. If you are happy with the services and software you may be using, especially throughout the current situation, please consider saying thanks or help these projects! Interested in supporting the Newsletter team? Read more at the bottom … ⌘ Read more
**R to @mind_booster: Metaverse? Yeah, that other new thing, haven’t you notice? Nevermind that book in my shelf claiming that Second Life is Linden Lab’s Metaverse, or years of Metaverse references older than Facebook in papers, conferences, etc.: the Metaverse is now.
https://www.wiley.com/en-us/Second+Life%3A+The+Official+Guide-p-9780470096086**
Metaverse? Yeah, that other new thing, haven’t you notice? Nevermind that book in my shelf claiming that Second Life is Linden Lab’s Metaverse, or years of Metavers … ⌘ Read more
“to limit that rise to 1.5C […] global carbon emissions will have to be reduced by 45% by 2030.
[…]
Instead, we are on course for close to a 14% rise in emissions by that date – which will almost certainly see us shatter the 1.5C guardrail in less than a decade.”
“to limit that rise to 1.5C […] global carbon emissions will have to be reduced by 45% by 2030.
[…]
Instead, we are on course for close to a 14% rise in emissions by that date – which will almost certainly see us shatter the 1.5C guardrai … ⌘ Read more
@niplav@niplav.github.io if he’s willing to be even more nerdy he could use https://lojban.org/publications/cll/cll_v1.1_xhtml-section-chunks/section-evidentials.html and possibly color-code them in some less important color than red
Corrupting memory without memory corruption
In this post I’ll exploit CVE-2022-20186, a vulnerability in the Arm Mali GPU kernel driver and use it to gain arbitrary kernel memory access from an untrusted app on a Pixel 6. This then allows me to gain root and disable SELinux. This vulnerability highlights the strong primitives that an attacker may gain by exploiting errors in the memory management code of GPU drivers. ⌘ Read more
using subscripts for probability assignments?
In typography, an asterism, ⁂, is a typographic symbol consisting of three asterisks placed in a triangle, which is used for a variety of purposes. Asterism (typography) - Wikipedia)