• Resolved strictly-software

    (@strictly-software)


    I have written 2 plugins that I use in conjunction with each other, Strictly AutoTags which automatically scans a post (usually imported from a feed) for relevant tags and then adds them, reformats the post and re-saves it (deeplinking, bold etc) – and Strictly TweetBot which allows you to automatically Tweet to multiple accounts OR the same account with different tweet formats. The usual trick is to use the post tags as #hashtags in the Tweet.

    The priority for the AutoTag plugin is 1 e.g add_action(‘save_post’ , array(&$this, ‘SaveAutoTags’),1);

    The priority for the Tweetbot plugin is 999 and on the publish (as I only want to Tweet when the post article goes live and not on drafts etc) e.g add_action( ‘publish_post’, array(&$this, ‘PostTweets’) , 999);

    However I have noticed recently that I am getting lots of articles added with tags but the tweets are using their default #hashtags NOT the post tags they are supposed to.

    I can remove the custom field I set that says the tweet has been sent, and re-publish the post and if the article has already got tags then I will get a new Twitter post (as long as it’s not a duplicate) that contains the correct hash tags.

    E.G two examples from my horse racing site today

    The first one was sent at 5:35pm > https://twitter.com/ukhorseracetips/status/395967181042618368

    New #Racing story Stratford blank 4 McCoy on http://bit.ly/HrN2Gu #HorseRacing #RacingNews

    When I logged in as admin, re-edited and re-published it then I got this tweet > https://twitter.com/ukhorseracetips/status/395976580842807296

    Stratford blank for AP McCoy > http://bit.ly/HrN2Gu #Stratford #APMcoy #Jezki #NationalHunt

    As you can see if you go to the actual article the 2nd tweet is using the post tags attached to the article.

    Everything was working fine up until a few days ago and I cannot think what has changed. I had to turn Omnisearch off on Jetpack due to it causing me issues with one plugin but nothing major has changed.

    Therefore I am thinking that the timings are out e.g the time it takes to scan the post and add the tweets before re-saving the article with new formatted HTML is too long and when the TweetBot plugin does its work there are no post tags for it to use which is why it reverts to the default ones.

    This is why when I re-edit an already tagged post and re-publish the tweets have #hashtags related to the post tags.

    Is the priority setting a real “chain” so if I had a job at 1 and another at 999 (like my 2 plugins) the 2nd job won’t even start running until any previous jobs have finished or is it a more parallel process OR even just a time based job e.g the priority 1 job starts 1 ms after publishing whilst the 999 job starts 999 ms after publishing so if the 1st job isn’t finished tough luck?

    I am just wondering what has happened here?

    Any help much appreciated.

Viewing 10 replies - 16 through 25 (of 25 total)
  • Thread Starter strictly-software

    (@strictly-software)

    Oh and by the way, I don’t know if this is important or not but from my first plugin (which I copied some code from another well know plugin as I didn’t know how to go about it) I have always added these functions to my funcs.php file just in case WP ever removes add_filters or add_actions.

    if ( !function_exists('add_filters') ) {
    	function add_filters($tags, $function_to_add, $priority = 10, $accepted_args = 1) {
    		if ( is_array($tags) ) {
    			foreach ( (array) $tags as $tag ) {
    				add_filter($tag, $function_to_add, $priority, $accepted_args);
    			}
    			return true;
    		} else {
    			return add_filter($tags, $function_to_add, $priority, $accepted_args);
    		}
    	}
    }
    
    if ( !function_exists('add_actions') ) {
    	function add_actions($tags, $function_to_add, $priority = 10, $accepted_args = 1) {
    		return add_filters($tags, $function_to_add, $priority, $accepted_args);
    	}
    }

    I don’t see how this would effect anything but I thought I should let you know in case you know something I don’t.

    Moderator bcworkz

    (@bcworkz)

    Wow! Too much information! 🙂

    You’ll have to excuse me as I didn’t study everything in detail. I do think I got the gist of things though, I appreciate the highlighting.

    I think the most significant observation from all this is it works perfectly from admin but not from CRON. This occurs with all plugins deactivated except for the tagging and tweeting ones?

    Maybe you need to simplify even more. Deactivate everything, tags and tweets as well. Create a super simple plugin that hooks ‘save_post’ and simply error_logs a message. Create a scheduled task that saves a minimal post. Still no error_log message? Then start tracing through whatever code executes scheduled tasks. Something is messing with the filter/action callbacks. Gotta find it.

    If the CRON does leave an error_log message, then incrementally add elements back in until it breaks. Of course, all this is just saying I don’t have any ideas either. But it would be important to be able to identify what is causing the problem if at all possible.

    While I do recognize WP is very inefficient in loading all sorts of crud on every single request, I haven’t investigated much the best way to mitigate this. My initial thought is to even conditionally include the plugin code in addition to conditionally instantiating the object.

    Of course when the plugin code is loaded, it is too early to decide if the plugin is needed or not, which is probably how we find ourselves here in the first place. The initial scope of my theoretical efficient plugin is to hook wp or init and check if conditions indicate my plugin would be needed. In your case, check for a POST request and the presence of a particular field indicating a WP post publish or update is happening. Only then is the class definition included and an object instantiated.

    This is strictly conceptual, I’ve no idea if it would really work, it’s simply my answer to “What is the most efficient way to invoke plugin functionality?” It came to me as I was typing this response. I’ve not investigated any feasibility at all.

    You clearly have a handle on debugging, I can’t improve much on what you’ve done. I’ll be happy to continue offering any insights I may have on the inner workings of WP. Beyond that, I don’t think I am of much help at this point, I am equally mystified.

    Thread Starter strictly-software

    (@strictly-software)

    Don’t worry I solved it!

    I thought I had put it in this forum but I must have been speaking to someone else.

    The problem was due to the is_plugin_active function which is only allowed to run when you are logged in AS ADMIN. Which explains everything perfectly (see https://codex.ww.wp.xz.cn/Function_Reference/is_plugin_active )

    I couldn’t run the same code from a CRON / GET request as I wasn’t logged in as admin so it bombed out on that line. But when I was in admin posting everything worked as expected.

    I have replaced that line of code with a check for my strictly_auto_tags wp_options array so if it’s there I know autotags is installed and can use that instead of the check for the plugin.

    It doesn’t solve the question of why so many plugin initialisers are called all the time (lots from the looks of things) which is why I asked the best way to declare objects (singletons or just $myobj = new myobj(); at the bottom of the page)

    Also someone could in theory have the plugin on their system – de-activated which would mean tagging wouldn’t run. But I do offer a “uninstall” when de-activating option so that should solve the majority of cases.

    Thanks for your help – although I was pretty sure I replied to it yesterday.

    Moderator bcworkz

    (@bcworkz)

    Well, that’s rather obscure. I reread the function reference and still didn’t get you need to be logged in as admin. The need to manually include plugin.php yes, but not logged on as admin.

    I’m glad you found the solution, that could have been seriously crazy making.

    Instead of checking if a plugin is active, could you use function_exists() as a test? If not active, some function for the plugin should not appear to exist.

    All the crud that WP loads for any single request is probably the one biggest thing I dislike about the package. It’s not really a problem for my site, I don’t get enough traffic, though page loads are still a bit slow for my taste. I just dislike it on principle. It could be a real problem on heavily trafficked sites. Sigh.

    Thread Starter strictly-software

    (@strictly-software)

    Hi

    It does say that the function is only available in the “admin pages” e.g

    NOTE: defined in wp-admin/includes/plugin.php, so this is only available from within the admin pages, and any references to this function must be hooked to admin_init or a later action. If you want to use this function from within a template, you will need to manually require plugin.php, an example is below.

    So I take that as having to be logged in as admin and using the admin_init hook OR including the plugin code.

    I’m not actually sure what within the admin pages logically means which is why I am presuming it is to do with being logged in as an admin AND in the admin area of the site when running the code.

    This would also make perfect sense to why I can post an article OR call WP-O-Matic in admin and the code was working okay but when I called the page in the plugin folder/test page in the root directory from a GET request it bombed out on that function call.

    I did put a reply up (or I thought I did – must have a dupe thread somewhere OR comments not submitting) which showed that when I moved that is_plugin_active code to the top of my test page and just below the

    require_once(require_once($_SERVER["DOCUMENT_ROOT"] . "/wp-config.php");

    That the test GET request was just dying as soon as it got to the is_plugin_active function call.

    This is what made me think the two were related.

    You are right a test for function_exists would probably be better as long as WP load in all plugins before any code can be ran?

    The reason I ask is, if AutoTags was loaded AFTER the tweetbot plugin would function_exists still be able to see all the functions in the AutoTags plugin?

    If WP loads in all the plugins first on every page THEN lets people do stuff with them it would be okay.

    However like you, I really don’t see the need to load in every plugin on every page. It really must kill performance to load in plugins that are only related to saving posts on pages where people are just viewing posts AND vice-versa.

    Could WP not have some sort of plugin_use tables/object that the plugin author defined where their plugin (or even each plugin action) was to be used?

    E.G if my autotagging plugin is only used when a post is saved then the code doesn’t need to be loaded when a page is displayed.

    Or if code is linked to a button that can only be hit in admin then (e.g to manually rebuild a sitemap) then it doesn’t need to load that plugin code in anywhere else in the site.

    This would allow WP to only load in the relevant plugins FOR the actions being carried out rather than ALL of them ALL of the time.

    You are right in that when I made my first plugin and delved under the covers of WP I was horrified at the amount of duplicate function calls and code being run. It must really hurt performance with all the duplication going on. It is also the reason I learnt PHP a few years back.

    I remember my first plugin was a sitemap plugin that I had to write due to getting out of memory errors when it was rebuilt each time.

    The answers I was getting from people was to just increase the memory allowance for it. It seemed like the same functions were being called on every loop iteration (e.g to get permalink structures for categories, tags, posts, pages etc) rather than just getting them once before the loop.

    So I decided to handle the problem myself, learn PHP, and write my own Sitemap plugin. It can either use pure SQL to build up the recordset instead. OR use SQL to get each section (pages, posts, categories, tags) and then PHP to join them together.

    With my plugin (which I still use even though the SEO parts are a bit redundant now due to Google/Bing changing how you can use their search engines to make requests), the maximum number of SQL calls to the WP DB is always 7, this is the case whether you have 1 or 100,000 posts on your site.

    With other plugins (at least at the time I wrote mine) the number of DB calls increased as the number of posts being outputted in the plugin went up.

    I did a little comparison test which you can see here > http://www.strictly-software.com/plugins/strictly-google-sitemap and you can see in the comparison table (about halfway down between my plugin and 2 others) which compares two different permalink structures:

    /%year%/%monthnum%/%category%/%author%/%postname%/%post_id%/
    /%year%/%monthnum%/%postname%/

    That the number of DB calls was constant with my plugin when compared to the others. It also shows the full amount of records (pages, posts, categories, tags which can be listed in the sitemap), Database calls and the amount of memory used for each (a small site and a larger one).

    This was a few years back now when I only had 7000 posts, now I have 40,000+ so it’s even more important that I squeeze every bit of performance I can out of the system and any plugins.

    I suppose this is why I do my deep-linking with my AutoTagging plugin on INPUT (when a post is saved) and not on OUTPUT (when it’s shown) as it reduces the amount of work needed (you may save once but display it 100,000+ times).

    I also ban 45%+ of all my traffic (bad bots, hackers, spammers, whole country IP ranges, whole Amazon subnets etc, short user-agents etc) to keep the traffic down to legitimate users.

    I need the code to be quickly loaded and optimised and I have had a real nightmare with a LAMP + WP set-up to get it to run as fast as possible without just throwing more RAM+CPU at it. The amount of PERL, BASH, MySQL optimizer tools and so that I have had to learn to get the stats I need is way too much, but then that could be seen as a good thing as they are all new skills for my CV!

    I am used to Windows (.NET C# ASP) and MS SQL (day job) which have beautiful diagnostic tools for improving DB speed, finding missing indexes and logging useful stats. This is why I find the lack of nice visual diagnostic tools on LAMP very poor in comparison.

    I have often thought that a tool that could link a servers load (uptime, CPU, memory, disk swap etc) with the error/access/MySQL slow query log etc so that you could see what URLs/Queries were being hit and by who (IP/Agent) when a CPU or Memory spike, error or connection issue occurred. Or the biggest hitting IP/UserAgent that caused the most errors etc would be FANTASTIC.

    I even got to the stage of nearly attempting to write one myself at one point. However the nearest I got before solving my own issues was writing another system check plugin which doesn’t load in all the WP code, copies the DB constants (to keep it quick and not reliant on any WP issues) and it makes scheduled HTTP requests to a site to log Server Load, No of SQL queries running, long queries, connections, time to load the page and some other stats. Then if there is a problem you can set it to auto optimize/repair your tables OR just send a warning email to you if problems are found.

    I still think a tool linking all those log files and server values (CPU/Memory/Load) would be great though!

    I even wrote a 3 stage WordPress survival guide for my own sanity and to help others moving from Microsoft to LAMP >
    3 part WordPress Survival Guide

    Whilst I am glad I now know PHP/MySQL/Linux/Apache etc there is sooo much I would change if I could re-develop the codebase for WordPress but then I have my own day job to keep me busy at the moment!

    Thanks for your help!

    Thread Starter strictly-software

    (@strictly-software)

    Also, I just realised that my answers that I had thought I had sent to you were accidentally sent to someone from Jetpack about a bug I had reported! Too many tabs open I think.

    They are here > http://ww.wp.xz.cn/support/topic/omnisearch-breaks-strictly-tweetbot?replies=6#post-4876129

    Moderator bcworkz

    (@bcworkz)

    After re-reading the function reference a couple more times, I don’t think the user has anything to do with is_plugin_active(). It has to do with the plugin.php file being loaded or not (What? WP doesn’t automatically load everything?) Something in the admin_init process loads this file, which does not happen with wp-cron. I would think if your plugin were to explicitly include this file the function would work even without admin credentials.

    As for using function_exists(), it would not work if it were called during load time. It would need to be called from ‘plugins_loaded’ or anything afterwards. ‘save_post’ or ‘publish_post’ are both plenty late enough.

    I think the problem with WP efficiency comes from it’s early roots as strictly an individual blogging app. The load everything approach was OK for that. Because it is highly extensible, it morphed into a CMS platform. It continued to grow organically, piling on added functionality to an ill conceived base. If it were conceived as a CMS platform from the beginning, perhaps it would have organization such as you suggest, as well as tools to ensure it stays efficient.

    The sort of software bloat we’ve been seeing really pains me. Instead of endeavoring to write more efficient code, the industry is content to simply throw more memory, processors, and bandwidth at the problem. Consumers are forced to pay for the latest bloatware to stay current, and then again for the newer hardware needed to run it.

    Thread Starter strictly-software

    (@strictly-software)

    Yep I know, too many people thow £$ at the problem (hardware/Memory/CPU) instead of actually debugging and solving the issue at the root (usually badly designed code, missing indexes, functions etc). The amount of performance gains I have had just from adding correct indexes or replacing @table variables with proper temporary #tables with indexes has been immense.

    The is_function test is working perfectly. I tried with the plugin de-activated and the tagging didn’t run and the tweets went ASAP, plus in the admin page I don’t even show the “Automatically linked with Strictly Autotags to ensure tweeting always runs AFTER tagging” if the plugin is de-activated (but not uninstalled).

    So that seems a better solution than checking for an AutoTag get_option value.

    If you notice the comments I accidentally posted on the other thread. I did create a test page that just called wp_insert_post with some test text to check the firing of the save/publish/finished_tagging hooks and it wasn’t working at all e.g no tags and no tweets.

    When I put that is_plugin_active code in the page bombed out as soon as it hit it. As soon as I changed that test with function_exists(‘ShowAutoDebug’) – I always have debug functions in all my plugins which contain the core name of the plugin – then it worked fine. So this solution does work.

    I can totally understand a system that starts out as one thing and then morphs into another. Once it reaches a certain size it becomes too large to rebuild from the bottom up and only small fixes/changes can be applied. However if you had enough developers ( I don’t know how many Automatic have ) they could work on a new version from the ground up WordPress 2000+ or something that was designed properly with thought for the future, all whilst the existing system continued to run.

    It is what I have had to do 3 times with our companies top selling jobboard software and sometimes it’s good to start from scratch just to remove all those old mistakes you know you would never repeat.

    The plugin loading does seem like overkill and I think you have fixed it now but in a version not too long ago on the home page I was having 230+ queries being run when the page loaded. Instead of one big query to get all the posts, categories, tags, meta for the 10/20 posts on a page (or even 10/20 queries to get post/category/tag/meta data per post) it was getting single record queries for each post, category etc in a row all with LIMIT 1,1 on the end. I have no idea why but I am sure a lot of the code could be condensed and network traffic reduced by returning all the data you need in one SQL per page (if possible) rather than 100’s of single record SQL calls.

    Anyway it is working perfectly and even though I have had to learn a hell of a lot of PHP/PERL/BASH/LINUX to get WP running fast it has been worth it.

    Thanks for your help

    Moderator bcworkz

    (@bcworkz)

    You’re most welcome. I’m glad my ideas are working well for you. I also enjoyed our OT chat along the way. One parting thought…

    However if you had enough developers ( I don’t know how many Automatic have ) they could work on a new version from the ground up WordPress 2000+ or something…

    Wouldn’t that be awesome! There’s quite a few devs working on WP core code, but they’re all or nearly all volunteers. It seems only a few are doing most of the work. I don’t see the concerted effort required for a major rewrite happening with this coding model. All their efforts appear to be towards improving the user experience and not towards more efficiency. Improved features is something more people would notice, which keeps the cadre of volunteers excited to be in on the bleeding edge of something. Understandable but unfortunate.

    Thread Starter strictly-software

    (@strictly-software)

    Always good to chat code n swap ideas with another developer!

    Thanks for your help it is all working smoothly now. All my posts are getting tagged correctly from Strictly AutoTags and then all my Tweets are going out using the correct post tags as #HashTags ONCE the event has fired (if both plugins are installed).

    Sweet!

Viewing 10 replies - 16 through 25 (of 25 total)

The topic ‘How does the priority parameter work?’ is closed to new replies.