• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

XF 2.0 Should I be using \XF::fs() for all file operations?

DragonByte Tech

Well-known member
#1
I'm finally running the latest DP, and I'm noticing the \XF::fs() is being used to write and check for the install-lock.php file, among other things.

Should I be converting all my code to use the FS for all file operations? Is there ever a reason not to use it (performance overhead not needed, etc)?


Fillip
 

Chris D

XenForo developer
Staff member
#2
If you are writing to or reading from any of these locations, then you will need to look at the equivalent functions within XF which are using these locations for guidance on how to use them (see FsMounts.php for the default mount points):
  • data
  • internal_data
  • internal_data/code_cache
Anywhere else and you don't need to worry.

If you are writing to anywhere within these locations then you should use the \XF::fs() stuff. The idea behind this is that the files can be hosted away from the local file system, e.g. a different drive, a different server, an external service, etc.
 

DragonByte Tech

Well-known member
#3
Gotcha, thank you :)

All my mods check for and erase a zero-byte file in internal_data to make sure newly uploaded versions don't cause DB errors by requesting stuff that isn't ready yet, and I have a couple that will be writing to internal_data.

I'll also have a wee look for references to the code_cache directory as that will be relevant for the Optimise mod (which I can't even make until I've found new features to add for it, you guys gutted it by implementing 99% of its feature set into the XF2 core, you swines :p)

Thanks!


Fillip
 

Chris D

XenForo developer
Staff member
#4
I'd recommending potentially being cautious about writing to internal_data for this and using the adaptable file system because if it's a check that runs for every user on every page load then you're potentially halting execution while it makes a HTTP request and waits for a response.

It certainly sounds like you're using it in a similar way to install-lock.php, but you might notice we've slightly changed how it is accessed now for the very reason I've just mentioned.
 

DragonByte Tech

Well-known member
#5
I'd recommending potentially being cautious about writing to internal_data for this and using the adaptable file system because if it's a check that runs for every user on every page load then you're potentially halting execution while it makes a HTTP request and waits for a response.
The existing checks run entirely in PHP-land, there's no checks once the DOM has started to render.

It certainly sounds like you're using it in a similar way to install-lock.php, but you might notice we've slightly changed how it is accessed now for the very reason I've just mentioned.
I'd be copying this util function:
PHP:
    public static function installLockExists()
    {
        return \XF::fs()->has('internal-data://install-lock.php');
    }
And using something like
PHP:
    public static function installLockExists()
    {
        return \XF::fs()->has('internal-data://dbtechCreditsInstall.lock');
    }
In a file utility class of my own.

That should be fine, and not cause any performance issues, yea? :)


Fillip
 

Chris D

XenForo developer
Staff member
#6
I'm mostly commenting on when and how often installLockExists() (or your equivalent) is called and I'm talking about delays in PHP execution. I mean we're probably talking still less than a few milliseconds in the normal case but if there ends up being temporary bandwidth/connection/load issues between XF and an external file host then performance could suffer throughout the whole site rather than, for example, just when a thread contains attachments to load from.

So your approach seems sound, but just be cautious about how frequently that file has to be checked. The install-lock is no longer checked for on every page load for these reasons.
 

DragonByte Tech

Well-known member
#7
So your approach seems sound, but just be cautious about how frequently that file has to be checked. The install-lock is no longer checked for on every page load for these reasons.
I've had a wee look, and there may be some ways of optimising this to minimise I/O.

In an ideal world, I would make it so that at the earliest point possible in the app initialisation, I could do a single check for the lock file and if it's found, remove every event listener and class extension belonging to this modification from the current request. In other words, the listeners and extensions would obviously still exist in the DB, but it would be as if the mod was disabled in the AdminCP prior to the update.

You might think to yourself that disabling the mod during upgrades is a good idea anyway, and you'd be right, but I'm trying to idiot proof my addons as much as possible here :p

The best solution I can come up with at the moment is to create a utility class that will check whether the lock exists once, then cache the result for the remainder of the request. That way, if the addon has 50 listeners and extensions that's called in any given request, there's only 1 file exists check, not 50.

EDIT: Also, what might be a good idea is for me to add support for a new config flag, something like $config['dbtechDisableLock'] for advanced users if they experience I/O errors or slow-down with their setup.


Fillip