Battle plan for migrating to .Net8

I can report that the issue has been resolved, and it is now working as expected.
There is a bug when running on MacOS inside a debugger, quitting the application makes .Net run in 100% CPU. Fortunately, this does not happen when the debugger is not attached.

Most features are working as expected, but the notifications / balloontips are not currently supported by Avalonia.

Next up for me is removal of AutoUpdater and replacing it with a simpler update checker.

2 Likes

Hi, I finally had some time to look at it.
I am really glad that it runs on .net8 without jumping through hoops with mono i.e. but still there are A LOT to be done to actually write like people are writing in .net nowadays (i.e. with IServiceCollection).

To do all of that I need to now few things:

  • can we change updater a bit?
  • how do you test it? Does running Unit Tests is enough? Does not seems so IMHO.
  • how do you run it? Gui Tray Icon project seems to be launching webserver and browser for me. I was expecting Avalonia GUI project.

Why changing updater? I am thinking we could reimplement a bit IServiceProvider i.e. and load latest implementations of interfaces from dynamically downloaded dlls without restarting whole process. Maybe it would be possible to achieve smaller updates? Though that will be probably quite hard.
Api could be updated with zero downtime like this for sure. I already did something like that twice.

obraz

Ah I just remembered that you want to have compatibility with previous version, so at least for first release previous shelling and running RealMain is necessary, I think.

I agree, this is not the end. But once we have a limping version of .Net8 out there, each of these changes can be done gradually and will not cause insurmountable merge conflicts. I would like to replace the dynamic loading of components with a build-time listing, make the backends fully async, etc.

Yes, I will work on that. It was delayed a bit because I needed to rewrite the update server for Kestrel.
My plan is to not make the updater compatible, but make the “last” version on the current updater aware that there is a new updating scheme.

The new version of the updater will not attempt to use the in-process update, it will just activate a new installer.

Which part? The updater?

That was how it worked for me on Windows and MacOS. It also launched the tray-icon.

I think there are some issues with dependencies. It would be problematic to unload/reload if something is active or there are cross-dependencies that needs to be updated (e.g., NewtonSoft.Json).

Also, sometimes we would need a new native application or dependency to be installed (especially on Linux) and this is not possible in pure .Net code.

ok cool

Whole duplicati.

Right now some tests are failing. Is it normal?
obraz

I does not work like that on Linux. Is it a bug or expected behavior

I think it should be fine. But there are bigger problems in that codebase. It is just idea I had that I had yesterday looking into the code and noticing that there are no IoC container at all.

Sounds like a bug. I would expect a tray icon to appear on Linux as well.

But perhaps we needs some special tricks? Are you testing on Ubuntu?

I did not investigate the tests. Based on the test name, I think that one should be fixed with cancellation token support.

Debian 12.

So how do you validate if your tests did not broke the app? Do you configure a new backup, backing up some test files and then restore them?

I have not validated everything yet, just ran a very rudimentary backup.

I did not want to spend time on fixing small things now, as they may be removed or fixed due to later changes. Everything needs to be tested on multiple platforms before I am confident that it works.

ok cool, I will try to write some selenium tests then maybe, to make sure that everything works after my own changes.

Thanks again.

Hey, can you have a quick look at this?

Started rewriting api/v1/serverstate endpoint. This is going slow since everything is global, static spaghetti code.

I started to change Webserver.Core project:

  • added EF context there, tested if it can be used with existing db
  • wrote few services to read the same thing the old code have (server settings i.e.) but in IMHO a bit cleaner way.
  • Added IoC based on microsoft IServicesCollection for new and old services.
  • Use this provider in few places in the old code, after everything is moved to IServiceProvider we could got rid of FIXMEGlobal class
  • modernize startup code for webserver
  • I was thinking also of removing settings from DB (using backup id of -2 seems like a hack), we could just use extra json file for asp.net core settings. Change this file when settings are changed by the user, and reload them on save with IConfiguration and IOptionsMonitor i.e. (IMHO much better than the old way) but a gave it a rest for now.

It would be nice to know if this going in the same direction you thought about.

Ah and I was thinking of doing API endpoint in the minimal API style instead of old ControllerBase

:joy:

Yes, I think ControllerBase was something from back in the old ASP days, so please remove it!

I will have a look, but I think anything will improve the previous hand-parsing of data.
Edit: I looked through, and it looks great! We will have some conflicts around the updater FYI.

That is nice to hear. I can limit myself editing stuff, but I need to know what to leave out unedited.

I think the whole web-api should be fixed, and the global stuff should go.
I did not think of it before I saw your commit, but I changed the updater code to fit with the split of binaries.

You can just ignore it for now if it is easier, and then we deal with it when it needs to be merged.

It does not seem to be bad from conflicts perspective… just few properties.

yep, that is the goal.

Added small comment, there.
Also: can we establish naming scheme for members? Resharper keeps complaining about me not naming fields with ‘m_’ prefix. Is this what we do in this project?
With that established it would be a bit easier without thinking what name should be, the tool can fix it for me :slight_smile:

Btw I found something like that:
https://www.litedb.org/docs/

Looks interesting, and have encryption. From like 7 years ago when I was working on Sqlite on mobile I remember encryption being some hacky way of doing key, and value encryption before read/write.
And I read somewhere that it a bit problematic in Duplicati too.

But this is just few minutes of me doing a research on the matter, it can wait for some better time.

Agree! But the Duplicati code relies on constraints from the relational database, so this has to be lifted when using a document database as it (usually) does not offer constraints across documents.

1 Like

What this thing supposed to be doing?
public bool LongPollCheck(EventPollNotify poller, ref long id, out bool isError)

1 Like

Ah ok, I replaced the GET method but omitted this wait and FE is just shooting 10 requests per 1s.

Can’t we do it like normally it is done? By i.e. setTimer(120s, () => update();) in JS?
Or websocket?

The code is there because websocket support was missing in the http server.

If you do the wait in FE, you get a delay in updates + CPU load when nothing is happening.

The long poll is a poor mans websocket and allows the request to be hanging for a long time with no activity.

I think the tray icon is also using this to “subscribe” to updates, and ideally there should be 0 CPU load when no backup is running.

If you know how to get websockets working in asp.net, we just need to update the FE and tray icon code.

Yes I know how to do it. I give it a gry.