39: Stress testing dependency management

Well, Happy New Year Sven.

Happy New Year.

Did you have a good break?

Oh, absolutely. Yeah, good break. Very relaxed. Not quite as cold as in Germany or in other

places. I've seen it's been really cold in Sweden. There's someone I'm following on

Mastodon and he's been subjected to minus 40 degrees Celsius.

Okay, that's a lot colder than it is here too.

Yeah, no, I can't stand the cold and just reading that gave me the shivers.

It's not very warm here. It's going to hit two degrees above zero on Friday this week,

but it's certainly not minus 40.

Yeah, no, that's just way too cold.

Did you have a good break as well?

Yes, I did. Thank you. Nice to see family, friends,

spend some time away from a computer a little bit, which was always nice to do, but ready

to get back to it and raring to go for 2024.


And maybe we should start there actually. So we should maybe talk about

some of the things that we hope to get to in 2024 with the package index.

Yeah, that sounds like a plan. We used to post

like things way back and we held that up for a couple of quarters, but then due to the way we

organise stuff that sort of didn't, it wasn't really feasible anymore. It didn't make much

sense anymore, but I think on a yearly basis, it's a nice thing to maybe look forward what

we're planning to do.

Yes. And of course, all of the things we're about to talk to today can change.

And will.

And will. Exactly. Yeah, exactly.

So, yeah, I think just in terms of I briefly thought about what's the rough plan. And I think

one of the things that I'd like to continue working on, and we started doing that a bit is

dependencies. We'll also talk a bit about that later on in the news section. We've started

tracking dependencies quite early on by just capturing the resolve dependencies,

which is the full dependency tree you get in a Swift package after package resolution. So that's

the transient dependencies included and the test target dependencies. That's literally everything

your package touches. And that's been in our database for quite a while,

but that's also not the best thing to report really for people who are inspecting a package.

You don't necessarily are interested in test dependencies or all the dependencies. You sort

of maybe want the first and direct dependencies and that sort of thing. We're starting to pick up

and we have those in the database as well now, the direct dependencies. So we can report in a bit

more detail what we've got, but there's a lot more work to do here to also prune up the test

dependencies and all that. And I think that's going to be really exciting because it's one of

the things that will give us a bigger ecosystem wide overview, just to the things you can do then

by looking at what packages are sort of central. They have lots of dependencies, packages that

depend on them. Is that dependency? Yeah, that's dependence. Now that's dependence or whatever,

dependence. That's the one. I'm kind of imagining we'd be able to maybe draw some graphs or

something around like these webs and see packages that are very cool. And we've talked in the past

about when we talked about the NPM ecosystem and the crates, the Rust ecosystem. There's some

statistic and analysis that they've done in their ecosystems that would be interesting to do in

Swift, in the Swift ecosystem. I'd really love to do that, try and replicate that, see if we see

some of the same problems there with the circular dependency graphs, which were kind of weird.

I wonder if there's something like that in Swift as well. All that sort of stuff falls

under that umbrella that I'd really love to focus on in the coming year.

And I know you've started doing a little bit of this already, not so much on the dependencies

display in the package index, but so building on some of the work that we already have in the

project for getting that list of complete, that total list of every type of dependency that we

currently have. There was a nightly process, or there still is a nightly process that runs

through GitHub actions, which goes and tries to find any dependencies that are dependent of,

sorry, that depend, no. I got it wrong. It finds any packages that are not in the package index,

which are depended on by other packages. And that process used to take about eight or nine

hours to run something like that every night. Yeah, yeah, exactly. It had increased to,

I think, nine and a half hours now, even because we've grown since we started doing this.

And yeah, this is a long one. And I know that we've, well, you just put some work into,

and we've just put into production a version of that script that now uses the dependency work

that we do in the main package index to shortcut all of those searching for dependency steps and

just read the dependencies out of our application. And that took the job from nine and a half hours

down to certainly less than half an hour, right? Yeah, it's like five minutes or something like

that, because it's effectively, we were previously crawling every package, downloading the package

manifest and doing a package resolution to get the package resolved out of it, which is something we

already do continuously in the Swift package index. So we have those things in a database,

and this was effectively just ripping that out, asking the database for everything in one go.

And that query is even faster. I mean, that query literally runs in 50, 100 milliseconds,

and it's the downloading of the data that maybe takes maybe half a second. And the remaining time

is then to validate these packages. But we have a very fast way now to find out which packages

are being referenced but aren't in the index yet. And that was really, really helpful to get that

nightly process under control. It also helped us find packages that we didn't actually find with

the other process in the past, because the way the other process worked was to download the

manifest of the main branch, of the latest version of the main branch. But what happens then is that

we have packages in the index that are old, that don't have new revisions, and they never moved

forward. And they were actually referencing, they had all the manifests that were referencing

package versions that weren't, that were only live at the time, but aren't live anymore.

This sounds probably way more complicated, and it's hard to follow. But the thing is,

we're now unearthing packages that are being referenced that we didn't actually see before.

So if you are following our Swift package updates, Mastodon account, you will see loads

of new packages appearing. And those are the packages we're now finding and adding to the

index because we've made that change. And we've also changed, we're now accepting forks as that

people are depending on, and adding them to the index, because they are packages like any other

package, and they're being used. So they should actually be in the index, so we can properly

account for all the dependencies we've got and have them in the index.

And this is the point I was going to make, and it's the influx of these additional dependency

packages has really tripped me up this week and made... So when I'm preparing for this podcast,

I go through the list of new packages to see what's interesting and what's been added.

And with all these, quite a significant number of packages, more than 100 packages being added

by this script, I made that job much more difficult than usual, because it's a whole

load of forks and packages that I just depended on that have maybe been around for years and years

and years that we might not feature on a podcast like this, but as you say, should be in the index.

And one thing that, in the context of what are we going to work on this year,

one thing that this has really highlighted for me is that we quite desperately need a feature

which shows which packages are forks of other packages. And if we have the other package in

the index, then we should also refer to that package because it's quite... In fact, I was

tripped up myself by a fork of plot, John Sundell's plot library, which is an HTML generation library,

which we use in the package index. And I was going through the list of packages and I saw plot go up

and I thought, "That's strange. We've definitely got plot." And I opened it in my browser and

looked at it and it took me a second to realize that it was my fork of plot that...

Was it your own fork? Yeah. I saw that flow come through.

And that deserves to be in the index, but it's also... It should be really obvious. Yeah,

it should be really obvious that that is a fork and not a brand new project.

Well, if any fork deserves to be in it, it's your own, right?

Well, it takes my total number of packages in the index up to two. We've got left pad,

which is the test package that we have. And now a fork of somebody else's work.

Nice. So yeah, that feature, we just need to

add a little bit of extra metadata to those fork packages. So just be careful if you see

new packages that you think should already be in the index, it may be a fork right now,

because we're not very clearly displaying that. There's a couple of things that I'm

interested in working on in terms of broad kind of themes for this year.

One is I'd love to do some more work on the package score feature. So we've talked about

this in previous episodes of the podcast and in blog posts recently as well. We have a

internal, in fact, not just internal anymore, it's now publicly available package score. And

you can see the score for any package that's in the index. But the list of kind of factors that we

use to score each package could be improved. And there's a thread open in the discussions

forum on the package index GitHub project, which we'll put a link to in the show notes.

If you have opinions on that, there's already a discussion going there.

I would like to do some more work on that this year, and kind of bulk up the significance of,

not the significance, because it won't be any more significant than it is at the moment,

but bulk up the kind of the evaluation of packages to promote better packages in the

index. So that's one thing I want to work on this year. And I think the other is something we've

been kind of discussing a little bit is over time, I don't know whether you remember, actually,

I know you will Sven, but I don't know whether anyone else remembers that when

the package index first started, it was entirely a metadata, metadata only information on the

package page. So we didn't actually display the readme file until quite a while after we launched.

And instead, it was it was purely metadata, it was it was a lot of the metadata that you see today,

even build compatibility and those results on the package page, and then a link to

the GitHub repository. And of course, over time, we and in fact, it was never our intention not

to have the readme file on there, it was just a matter of, you know, getting things done.

And obviously, we did add the readme file. And here we are today. But over time, that metadata

section has grown and grown and the compatibility matrix takes up quite a lot of space. And it

pushes that readme too far down the page. So one of the things that we've been chatting about this

morning, actually, is whether we can look at that page design again, and maybe think about trying to

pull that readme file back up the page a little bit, we're not going to get rid of the metadata,

there's definitely going to be metadata at the top, because that metadata is really important.

But it would also be good to have at least the first few lines of the readme visible

on a reasonably sized screen, which is currently not the case.

Yeah, definitely. I think the there's ways to condense that down a bit, I think,

especially going forward, we might see fewer Swift versions that we need to display,

you know, that sort of stuff. And the compatibility matrix, as you mentioned,

might be might need to shrink down a bit anyway. It's we got all these Apple platforms, maybe

there's something we can do there. It's it's, it would be nice to pull up the readme a bit more.

Yeah, agreed.

But of course, I'm sure we'll do a whole load of other things as well.

Yeah. Just to mention, there's there's no year without new Swift versions. So that's

certainly something we'll be looking at trying to add those as early as possible.

Who knows when Swift 6 will come out if it's this year. Rest assured, we'll be looking at

compatibility info there because we we know that Swift 6 will have will be potentially

have sourcing compatibility. So it's it is possible to have syntax changes there.

That's allowed. So that's allowed. That's something that is that is in the cards,

I should say. And we'll definitely make sure that we test this early so people can

can maybe use us there as the if they haven't set their own CI up or or just want to rely

on another service to have a look there and give an overview. So we're definitely trying to be

prompt with testing for Swift 6 as much as possible.

So when we've been doing a little bit of planning already with this and talking about Swift 6 and

you know, there's a Swift 6 strict compatibility mode, which is the concurrency checking that's

coming in that's potentially source breaking in terms of like there were things that with Swift 5

it would let you do and in Swift 6 it will it will strictly stop you doing some of those things.

And there's two modes you can run the Swift 6 compiler in, which is with strict compatibility

testing for concurrency issues on, which I believe is going to be the default for Swift 6.

And then Swift 6 in Swift 5 mode, which is if you want to use the Swift 6 compiler,

but you still need Swift 5 concurrency checking, then you can switch the Swift 6 compiler into

that mode, which we're not going to test for explicitly. But what we will be doing

is testing the latest version of Swift 5 at that point as well. So you'll have Swift 6

compatibility with strict mode on and then 5.9, 5.10, whatever it is at the point that

Swift 6 comes out, we'll be testing the Swift 5 mode. Have I got that right?

Yeah, exactly. I think there's, we don't expect there to be a significant difference or any

difference at all between Swift in 5 mode versus the latest 5 version at that time. So that's why

we're not really going to, we're not planning to spend effort on running those two modes in parallel.

Exactly. So, but of course we don't know, I don't know whether the public, the schedule

for that has been announced yet, but I'm not aware of it. So it's something that we will do

as and when those versions come out. Yeah. And well, I think there's no new

Apple platforms to plan for this year, right? Vision OS just came out and is...

Well, the good news is we already support it. Yeah, we already do. And I'm not aware of any

rumors about new Apple hardware or OS releases that we might be planning for. So I think on

that front, we're well covered at least. There is no new Apple hardware until the

day that Tim Cook announces it, right? It doesn't exist until he steps on stage.

That's how that works. Yeah, exactly. Yeah. I think you're right.

I think Vision Pro and obviously the Vision OS SDK, which did get announced, I think yesterday,

the release date for that, which I think is February 2nd, maybe, that we already support

in our compatibility matrix. What we will do is we'll update the version of Xcode that we use to

do that compatibility checking to 15.2, which again, I believe was released yesterday,

but really no changes that we need to do there. Yeah, exactly. And my understanding is the

515.2 beta one, I believe that we were using already had the... My understanding is how the

Vision OS SDK version that is actually shipping. So there won't be like the compatibility right now

should be up to date already, even when we change to the newest 515.2 version, that should all

remain the same, fingers crossed. That's great.

There is another bit of news we may want to briefly talk about. And that's a really interesting

post I saw coming through this week on Mastodon. And that's a blog post about

when everything becomes too much by Frost Abukadi. Did you see that, Dave? Did you have

a chance to look through that post? I did. You sent me a link to this earlier

today. And I did. I did give it a read. Yeah. So this is really fascinating. And

what a mess. What a mess. Yeah. And this is not about pointing fingers or just, you know,

laughing about what's going on in NPM. This is just general ecosystem stuff. And NPM

is pretty much, you know, it's a huge ecosystem, like orders of magnitude bigger. And it's sort of

the things they hit, they are going down paths that the Swift ecosystem hasn't even begun walking

down yet. So there's interesting stuff there. You could say they're stress testing dependency

management. Pretty much, yes. Yes, they definitely are. And some of this is inherent in how

the ecosystem works. I think it is fair to say that node packages are smaller. You know,

they bundle up smaller chunks of functionality into smaller packages. And that by nature then

have way more dependencies and all that. And that has a knock-on effect to how that works. But

that is just one aspect of it. And the other is just more exposure to more people that try

things. And what this is about is that someone created an NPM package called everything,

which, well, depends on everything. They have effectively made this package depend on every

package in the NPM registry. And just think about what that means. If someone went on to do NPM

install of that package, they would effectively DDoS themselves because it would start downloading

every package. And this just sort of spiraled out of control because it compounded with another

problem that happened in 2016. And that was the LeftPad incident.

Ah, LeftPad gets a second mention of the episode.

Yeah, second mention. There you go. So in 2016, the NPM world broke because the author of this

LeftPad package removed it at the time. And this was actually a package that was used in lots and

lots and lots of other packages. And that led to problems because then they wouldn't build anymore.

Lots of CI systems, is my understanding, started breaking and failing because they couldn't resolve

that package at build time and all that. And as a consequence of that mess at the time,

they established a rule that you can't unpublish a package once another package depends on it.

And now you can imagine what happened once everything started depending on every package

in NPM. That meant that no package could actually be unpublished anymore. So it was

effectively blocking everyone from unpublishing their packages after this. And just imagining

about how, you know, one thing that was made or one rule that was implemented to fix one thing

can then completely backfire if another thing goes horribly wrong or, you know, another,

you could call it an abuse case happens and sort of messes everything up. I don't want to be in

the shoes of people trying to manage this whole mess, but it must have been really horrific.

I think they found a solution in the end by just pulling the whole org down of the people who

published this. The people themselves actually were apologetic when they realized what they've

done. They want to do the right thing and unpublish the package, but they couldn't

themselves anymore because they'd been blocked out of unpublishing by, I guess, someone using

their package or something like that. I don't remember what the actual effect there was,

but it was just a big mess, but quite interesting as a look ahead.

I think it said in the post that the solution was to make the repositories, the everything

repositories private. And I think that's the workaround that they got to, because you can't

stop somebody taking a repository private. So they must have had to deal with that situation.

And I think that's what let them unwind this, if I read the post correctly.

But I mean, I do feel for the person who did this, because I genuinely believe that it was

done as a little bit of a lighthearted joke, or certainly its intent was a lighthearted joke.

But what a mess. Yeah, I mean, it's, can you imagine sitting there and suddenly realizing,

you know, it's like when that production incident happens and you suddenly realize you are connected

to the wrong database when you drop the tables. That's the sort of feeling that must go through

you. I mean, unless you really do it with the intention of breaking stuff. But if you didn't,

and I don't think they really did, then that is rough.

And it's the kind of thing, I mean, certainly,

Swift is a very different dependency environment than NPM. And we don't have this kind of situation,

or even really the potential yet for this kind of situation. But I think it's good for us to be

aware of what's happening in these other dependency environments. And certainly this one,

when, as I read more and more of this post, I thought, "Oh, this is, oh yeah, this is really,

it's really, really bad." I would encourage you to read the post. It's really good. Yeah.

- Yeah, we'll add a link to the show notes for people to read up on this.

Shall we do some packages or...

- Yeah, we could do some packages. Actually, I have a bonus extra little package,

which is not really a package recommendation this time. Well, but it's not in my normal theme of not

recommending a package. There may be one of those coming up later though. This was something I

spotted as I was doing a troll through the RSS feed. And I really liked the marketing approach

that this package has, which is to have no readme file whatsoever. So there is no information about

what this package does in the readme file at all. The name of the package is VGSL and the package

description says everything you really need to know. It's a very good Swift library. So that's

all you need to know. You should import this package immediately because it's a very good Swift

library. So, but no, I do have three actual recommendations as well. And the first of them

is by Daniel Lyons and it's called Plus Night Mode. And one thing that I... So I bought a new

watch this year in September or October, whenever they came out. And I don't know whether it's

something specific to the new watch. I think it may be to do with a new watch face, but when the

ambient light in the room is dark, the face and everything on it turns red, which is a really nice

way to not strain your eyes in the evening, or if you wake up at night or something like that and

try and look at your watch. And it's a... So everything goes kind of monochrome, but not

black and white, red and black. And this package by Daniel is a Swift UI view modifier, which you

can add to the bottom of any view hierarchy. So your entire navigation stack, for example,

could have this view modifier on it called Observing Night Mode. And you can pass a switch,

a Boolean in there to turn night mode on or off, which is something you'd have to track yourself.

So this would be an app specific feature. And it basically turns every view in that view hierarchy

into a red and black monochrome view, no matter what the original appearance of it was. And I

think that's lovely. I think, first of all, there's a couple of nice things. I think it's a

great feature. But secondly, I love the kind of cascading nature of Swift UI view modifiers in

that if you add them to the top level, then you can just do something like this, which would be

very difficult to manage in UI kits. I mean, you could still do it in UI kit, but it would not be

as easy as adding one view modifier in a UI kit. So I like that. And I thought it was worth mentioning.

- Yeah, I love that about Swift UI as well. I think the redacted stuff works the same way,

right? Where you can stub in, I don't know how best to describe it, redacted UI elements,

like text is not displayed as text, but as placeholders, like rectangles and stuff. I think

that's really nice and really powerful that you can just tack this on and everything just changes

into a different mode. I think that's really fascinating and super useful.

- I hope apps take advantage of this because I'd love to see this feature in apps that I use.

- Yeah, I have the same. I love this about the watch where it turns red. It's really nice.

Right. My first pick is called package-benchmark by Joachim Masila.

And this is a great package when you're looking to benchmark your code.

What it effectively does, it gives you a function or instrumentation to run a closure that gets

benchmarked. And it supports many, many metrics like CPU time, both like actual CPU time or

work clock time, throughput, memory allocations, threads, like how many threads you're using,

disk stats, all sorts of things. There's an amazing range of metrics you can track.

And I've been following this package for quite a long time, but I've always delayed talking about

it because I wanted to really give it a try. And it was clear from looking at the readme that this

is super comprehensive approach to benchmarking, but yet you'd also need to invest a little time

to understand what it reports and why that is important. That sort of held me back until I

actually sat down and tried using it. And it's not because the package itself is making this

complicated. It's because the topic is actually complicated and more complicated than you might

think. And that these details aren't ones that you should just gloss over and just take an average or

minimum when you benchmark stuff, because that's the thing you sort of reach for. I certainly,

whenever I benchmarked something in the past, you run it a few times, you look at it, well,

there's not too much jitter. I'll take the best one. You never really know what you're doing.

Typically when you measure, you do it a few times, you maybe calculate an error rate based on the

standard deviation, that sort of stuff. The thing is, when you do this, there are certain assumptions

that go in when that is actually valid and when it isn't. And mostly, almost always when you're

measuring benchmarks, these assumptions are wrong because of the way the distributions are shaped,

you can't actually calculate a standard deviation. And it doesn't make sense. And the framework

really leans into that. So what it does when you run a benchmark, it gives you so-called percentiles.

So it gives you a range of percentiles and measurements for those. So what that means,

a percentile is, let's say, percentile 50 means you're halfway through your distribution.

Everything is at least as fast as this and not slower. And the higher percentiles, for instance,

P100, 100th percentile means this is the slowest result you got. And the first one, which is called

P0, is the fastest result that you've got. So effectively, what this does, it gives you

certain points along the curve of your distribution. And it really drives home

the point that you shouldn't be thinking of your distribution as like a normal shape,

you know, like normal distribution. But it's really, really different. Just forget that

this is a normal distribution, because it won't be. And that's what I really liked. It's not

something you just drop in and then get numbers out and you walk away with the numbers, because

it gives you many numbers. And you really need to understand what you're trying to do.

And especially what you're trying to measure, what your requirements are for your system,

how fast it is actually supposed to be, and how fast is the slowest result supposed to be. And,

you know, it's making you think about the thing you're actually trying to achieve.

And I found that really interesting. And I had a couple of questions to Joachim

ahead of time, because I wasn't sure what this actually means and how to interpret the results.

And he was super helpful, gave me some pointers. And we'll add these to the show notes. There's an

interesting talk about by Jill Tenney, I think is how you pronounce his name,

about why normal distributions, these are normal distributions, why you should be looking at

percentiles and what you should be looking for when you do run these kinds of tests. And yeah,

I think this is really great. This is one of these packages where you start looking at the package

because you think it's useful. And then you end up going down a rabbit hole and learning really

a lot about a domain that you didn't know a lot about. And that really gives me, just looking at

the package and the documentation of it and the breadth of it, you know, like these, all these

different metrics and the care that has been taken to give you controls and knobs and, you know,

allowing you to set these thresholds, make it configurable, gives you really high confidence

that this is a really worthwhile thing to invest time in and use. And I know I've seen this pop up

in a few places, this package. It's been being used in quite a few projects to measure benchmarks.

So I think it's really fascinating. And give this a look if you want to benchmark stuff,

I think this is the perfect place to start. - That's great. Are we going to use it with,

because we have query performance tests in our code base, right?

- Yes, we do. I might try that. There's some, another place where I want to use it first,

but it's certainly something I'd be interested in doing more because right now we're doing really

the bare minimum of just, effectively we're not as much benchmarking, we're sort of snapshotting,

we're baselining, you know, we're trying to establish how fast is this if I run it once,

and then we record that time and we effectively see if we get slower. So we're not really ensuring

that we're hitting a certain speed, we're tracking how we're getting slower over time.

The way I like to look at it is that it's more of an indicator than an actual test. It is,

you should be aware that things have got slower. - Yeah. I think if I was asked what's this for,

I'd say this is to see if we suddenly have a query that runs two times slower, because that we would

see and that would be important. And this has actually happened. And that's what this is for

really to not accidentally, because SQL queries are really easy to just tweak a little bit and

then have huge performance regressions that you don't notice, especially you won't notice it if

your dataset is small. And what we're actually doing is we run it against our staging database,

which has a comparable dataset to production. So we would see if a query is really bad all

of a sudden, we would see that by looking at the, we're not looking at the runtime,

we're looking at the cost, which also isn't perfect because the cost is an estimate,

it can be wrong, but it is a, in my testing, it has been a fairly decent indicator of what's

actually going on. So this turned into a much longer packaged recommendation than usual.

But we haven't finished yet. Cause I was going to say the only, the only slight downside to that is,

is that because that CI step is not a mandatory CI step. What we quite often do is something will

slip by just a few milliseconds and it will start the test failing. And it takes us a few weeks to

maybe get around to updating those benchmark scores. And so if anything doubled the query

performance in those few weeks, we'd never know. Well, actually we would, we'd never know until

we came to update the benchmark scores. And at that point we'd realize, and there we go. But,

but, but yeah, but I mean, who's perfect, right? Yeah. I mean, that's the thing. This is hard to,

to automate because A, we want to, don't want to be running this all the time.

Like auto updating, right? You need to review these new numbers, right? You need to put them

in somewhere. We need to baseline somehow. And because Swift package manager doesn't have the

same affordance to do these, what's it called in Xcode where you can, you can baseline tests,

right? You can have performance tests in an Xcode and baseline them automatically because we can't

use that due to the way we're running tests. We sort of have to do that bit manually. Otherwise

that would be really great if we could do that and then just review the changes and approve them.

That would be ideal. Right now we can't, I mean, the best thing we could probably do is,

is write a, like the Pointfrico guys have done this auto snapshotting thing we could, but you

know, I've already spent way too much time instrumenting this. I think I'm not gonna,

I'm not gonna take it even further. This is, I do this once a week and that's, that's fine. So

it's not too much work at the moment. So my next package recommendation is by

Navin Chauhan. And this is something that I never expected to see in a Swift package. And I was,

I was kind of delighted when I saw it. It's called Swift Gopher. And it is a, a less than

one month old implementation of the Gophers, both server and client written in Swift. Now

I'm pretty confident that there are people listening who will not remember Gopher.

Do you remember it Sven? I do remember it. I saw it early on,

but I actually never used it. I know it's one of these, not ethernet, internet protocols, you know,

like FTP, HTTP, that sort of stuff. But I don't, what did Gopher actually do? It was, I don't

remember. I also, so I did, I think I did use it like once or twice. I remember on the old

Unix machines at university. I think there was still a couple of Gopher. I think Gopher was

mainly over by the time I even got access to the internet. So when I was at university, which is a

very long time ago, the internet was really only just becoming something that you could get access

to even in academical institutions. Certainly there was no home internet access at the time.

And Gopher was kind of dying at that point. So it was really early. But what it was,

was it was a precursor to the web and you could Gopher into a server. And it was like a step

up from Telnet. So Telnet, you basically got a remote console on the server. That's what Telnet

basically did. And Gopher was a way that you could fetch information and then post information back

to it in a text-based interface in the very early days of the web. But it's not dead apparently,

because Navan has written both the client and the server and you can run a Swift Gopher server

and you can connect to it with the Swift Gopher client and you can fetch information from your

Gopher server. It's a bit like these very early BBSs. I have no idea how that actually used to

work. So I do remember those. So that was really one of my first experiences with the internet,

which was the Telnet BBS systems. The only one that I remember by name was a Telnet BBS called

Skynet, which is a very original name for a BBS. And you would connect effectively using,

you'd effectively get a kind of shell into the server and it would be this BBS system that you

could leave messages for people, you could read messages, you could send messages, you could post

on public forums, I think, but they were very, you know, it was a very different to anything you'd

see today, but it was all through a kind of text, a terminal style window. And I remember the speeds

that we were able to have at the time, you could see the terminal screens drawing character by

character. So it was, it was early, early days of the internet. Well, Gopher, I didn't have that in

the cards as a package. I was pretty confident that that would be all mine. Yeah. Well, this

is one of my traditional recommendations, which is not a recommendation. Oh, is that what it is?

Although I do think we should, we should maybe consider supporting Gopher for the package index.

So we don't neglect those people who still want to use a Gopher client to fetch package information.

You can fetch your package of the day. Exactly. My second pick is called WebSocket Actor System,

and it's by Stuart A. Malone. And that's, I loved seeing this. So I've been following

Apple's distributed actors package with interest for quite a while now. But in the past, I've,

I've really struggled. I've tried a few times, but I've struggled with creating a proper example

that would work across nodes. So the repository comes with, with an example, tic-tac-toe the Apple,

Apple's distributed actors package, and I've played around with it, but I've never really

gotten it to work properly in a, in a local setup. And, and Stuart has really done all the hard work

here and created a package and then also shipped an example and explained how to use it. We can

set up a distributed actor system based on WebSockets here to communicate between nodes,

where nodes really is just another distributed actor instantiation. So it's really fascinating

because from a dev point of view, you're effectively just calling into an actor and

you don't even realize or know whether it's local or in another process or on another machine

across the network. And that's the beauty of this, of these distributed actors. It abstracts away

all of this and, and all of this message passing and, and encoding decoding is, is handled by the

library which is really nice. And Stuart has chosen WebSockets here as a transport and I think

JSON under the hood as a, as a exchange format, but you actually see none of that. So you really

just have actors and you, you know, you, you connect and then call functions with try await,

you know, like normal async functions on the actor that you've just resolved across the network

potentially. Now I haven't tested, I've actually used this in a little example to see how it works,

but I haven't tested what this means in terms of efficiency, resilience, error handling,

that sort of stuff. It does claim to automatically reconnect after failure. So it has some

affordance for this. And the other thing that's really nice about this, as opposed to a normal,

traditional HTTP rest API, for instance, is that you can call methods, actor methods on

the service you connect to, but the other service, you know, can also do this. So it's actually

really nice if you want to have a server that calls back to you as a client, you know, imagine

it's like a push mechanism, right? Whereas normally you talk to an API, you'd have to

pull the API to understand if something's there for you, you know, if something has something to

respond. But in this case, these two nodes are really peers. So if there's something happening

on the server, it can actually call into the client and say, look, this just happened, you

know, handle it. So that's really nice. And that might open up use cases that are quite powerful.

So, yeah, I really wanted to highlight it because I'm really interested in the distributed actors,

and I haven't seen a lot of packages actually using it, or even like proper applications using

it. And maybe this package WebSocket actor system can be a building block for someone who's doing

something with it. I have sort of a couple of ideas how we might actually be using it

in the future. That's why I'm super interested in this whole domain. And I've really loved seeing

this package come around. Are you ready to share those ideas? Well, I mean, it's no secret we're

running a build system, right? And right now our build system is... I figured that would be it, yeah.

Yeah, I mean, this because we have components that talk to each other.

And we're currently using GitLab as our queuing system. And if we ever have need to change that,

I'm sort of toying with the idea that rather than building some sort of HTTP-based system,

maybe this would be a good use for actors where the actors are the builders and they report back,

that sort of thing. I have to talk to people who know more about these kinds of systems if

that's actually a good idea, but it strikes me as something that might work really well for us here.

I don't know. I think these things make me overly nervous because they feel... There's no judgment

here on the actual reliability of this because I'm completely uninformed on the actual reliability.

But my perceived reliability is... I'm suspicious. Yeah, I mean, this is why I said I haven't tested

this in terms of efficiency, resilience, and reliability. I think that's really

a key thing to understand. But it's also true that distributed actors is based on tried

technology. So there are actor systems out there already. And Conrad, his last name escapes me

right now, at Apple, who's working on these systems, he has lots of experience with this.

And this is Apple's adaptation of actors. And this is not entirely novel, is what I'm trying to say.

Like, this is not completely uncharted territory. This is Swift's take on a system that exists. I

think Erlang has this in a certain sense. There is certainly a Swift spin to it. But I think we're

not, you know, like complete greenfield here. I think there's lots of reasons to approach this

with interest and see how it actually works and understand, especially if this is a good fit,

right? Because I think it's also important to stress that distributed actors aren't intended

to replace every distributed system, right? There are reasons why HTTP is really good. Because I

think if one reason I can think of where you probably wouldn't want to replace it, if you

need caching, that sort of thing like this or proxying, you know, like HTTP as a protocol

allows you to do lots of things where your services don't even know that they're happening,

because it's just a plain standard protocol. You couldn't, I think, insert anything like that into

a distributed actor system and expect it to still work, right? They really rely on talking to the

other end of the system that is as the same part of the system. There's no expectation of this

being proxied or load balanced or anything like that, is my understanding. Again, I might need to

talk to people who understand this way better than I do, to really get a feel for this.

We just continue with our reputation as the best research podcast in the world.

And with that, I think we should probably wrap it up for this episode. We will be back in a

couple of weeks with some more news and some more package recommendations. But until then,

we will say goodbye for now. Yep. Goodbye. See you in two weeks. All right. Bye-bye.

Creators and Guests

Dave Verwer
Dave Verwer
Independent iOS developer, technical writer, author of @iOSDevWeekly, and creator of @SwiftPackages. He/him.
Sven A. Schmidt
Sven A. Schmidt
Physicist & techie. CERN alumnus. Co-creator @SwiftPackages. Hummingbird app: https://t.co/2S9Y4ln53I
39: Stress testing dependency management
Broadcast by