appstream icon indicating copy to clipboard operation
appstream copied to clipboard

Provide systemd unit to refresh cache on updates

Open dbnicholson opened this issue 3 years ago • 3 comments

On stateless systems like ostree, the appstream cache needs to be rebuilt at runtime after system updates. The way we've typically handled these things at Endless is to add a systemd service that uses the ConditionNeedsUpdate option. That way it runs during boot after an update but not at other times. This would allow us to ship appstream data in the OS at /usr/share/app-info.

You can see an example of this type of unit in systemd. For systems that make use of the /{etc,var}/.updated scheme, this rebuilds the linker cache after an update. On classic stateful systems that don't use that scheme, the unit never runs as it's expected other process take care of updating the linker cache. For example, dpkg or rpm post scripts.

Anyways, I think the unit would essentially be this:

[Unit]
Description=Rebuild Appstream Cache
Documentation=man:appstreamcli(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=local-fs.target
Before=sysinit.target shutdown.target systemd-update-done.service
ConditionNeedsUpdate=|/var

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/appstreamcli refresh-cache

[Install]
WantedBy=multi-user.target

Does that seem like something that would be acceptable here? I can put together a PR if so.

dbnicholson avatar May 06 '21 23:05 dbnicholson

I thought of another potential use case for this - triggering cache rebuilds on input file updates. This would apply in the traditional stateful OS case. For instance, currently the apt hook directly runs appstreamcli refresh-cache, but that could instead be triggered by the population of /var/lib/app-info. Or in the case we're looking at for Endless, gnome-software refreshes our external appstream file and installs it to /var/cache/app-info/xmls.

In both cases you could have a systemd path unit that triggers the above mentioned service when changes to the system appstream input paths happen. My understanding is that it will look for xml, xmls, yaml and icon subdirectories in each of the potential system paths. Those are /usr/share/app-info, /var/lib/app-info and /var/cache/app-info. I think in the /usr/share and /var/lib cases, you could put a recursive watch on the entire directory. In the /var/cache case I think you'd have to have to use the separate subdirectories so that updating the cache files in /var/cache/app-info/cache didn't cause a loop.

dbnicholson avatar May 10 '21 15:05 dbnicholson

Hi! So, in general, I think I would absolutely accept this change as a PR - it's a good addition, and something I had thought about before as well. Could make sense to put it behind a compile-time switch at least initially though. In the long run though there is a good chance that the system-wide cache will go away - the cache is extremely efficient and avoids duplication of data on multiuser systems in their home directories, but it is also quite complex to juggle a non-writable and a writable cache and handle cache invalidation. Also, with a high usage of Flatpaks, it is less valuable unless Flatpak itself would compile the cache for system-wide installed Flatpak apps.

Does systemd immediately run the service once something in the respective watched directories changed? Or will it just run the service on a reboot then? In the former case, this could possibly replace the dpkg trigger mechanism (with some safeguards so we don't update the cache over and over again).

ximion avatar May 10 '21 16:05 ximion

Something like this may actually also help with issues like https://github.com/ximion/appstream/issues/365 (at least if used for Flatpak stuff)

ximion avatar Apr 10 '22 01:04 ximion