-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Profiles: Add activity when added as a presenter for Learn workshop #84
Profiles: Add activity when added as a presenter for Learn workshop #84
Conversation
@@ -150,6 +151,71 @@ public function maybe_notify_new_published_post( $new_status, $old_status, $post | |||
$this->notify_new_blog_post( $post ); | |||
} | |||
|
|||
public function insert_post ($postId, $post) { | |||
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid the second firing action triggered by Gutenberg.
(For the case: Publish->Switch to Draft->Publish Again)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is REST_REQUEST
a reliable way to detect that sequence of events? And is that a common occurrence?
At a quick glance it seems some of the other notification types don't try to prevent duplicate activities when something is published twice. It might be overkill, but if it's common then as a general solution I would consider using postmeta to store a list of notified actions to prevent dupes. Perhaps that's better done on the profile API side - @dd32 do you have an opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since wp_insert_post
would be fired twice because of Gutenberg (according to these two posts: post1, post2) and causes the issue showed in the screencast below. (You can see that there is another updating... after published, making the account rentest have duplicate activities for the assigned presenter)
Screen.Capture.on.2022-07-12.at.04-04-42.mp4
I first tried the suggested solution brought up in post1, which is to use wp_after_insert_post instead, but the result didn't change.
So I then use the method mentioned in post2, which is using REST_REQUEST
to detect the REST API fired by the Gutenberg editor.
It does smell though... not sure if there's a better way to handle this.
using postmeta to store a list of notified actions to prevent dupes
I might need to ask you more about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since wp_insert_post would be fired twice because of Gutenberg
You should be able to look at the metadata of the insert I believe, and see the state change somehow (I'm guessing post_status: auto-draft -> draft -> published maybe?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be overkill, but if it's common then as a general solution I would consider using postmeta to store a list of notified actions to prevent dupes.
Dupes should be able to be handled on the profiles side, every activity entry has a contextual link/id/etc.. but avoiding sending duplicate data in the same pageload is obviously beneficial from a performance standpoint..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, that's interesting about the extra call to wp_insert_post. I wonder if this is the cause:
Some plugins incorrectly make a second REST API request to save meta after a post has been saved because the author doesn't understand the core data API and doesn't realise Gutenberg will send the meta for them if they register it and update the posts meta directly. This is where that comes from, and it's bad practice
I don't know how the presenter metadata is handled, but it's possible that (or other postmeta) is causing the duplicate call. That might explain why you were having trouble fetching the postmeta from the transition_post_status
hook - maybe the meta is only stored in the second call, after the post status has changed. I'll do some testing and see what I can turn up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found some discussion here, I guess it explains why this happened.
WordPress/gutenberg#12903 (comment)
As we know that Gutenberg sends two requests when we hit the Publish/Update button:
a) Request to WP REST API to create/update the post
b) Request to post.php to save/submit the metaboxes
a) Gutenberg saves data via one or two requests; the second save request only fires if there are meta boxes, so a plugin cannot depend on this request happening.
b) If there are going to be two requests, the plugin can't necessarily depend on the first request, because the first doesn't contain all the data for the post.
|
||
foreach ($presenter_wporg_username as $username) { | ||
|
||
sleep(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we got the rate limit, so sleep a second before the next call out.
(For the case that author and presenter are the same person)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think sleep()
is a good solution in production, though it's useful for diagnosing the problem. It could theoretically lead to unexpected UI delays when publishing a post. Better to find a more robust solution: either find out why the timeout is occurring and solve that, or schedule the function to run in a cron job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should remove this. It was added because at first I was putting the logic in transition_post_status
.
Now that the logic is under wp_insert_post
, the problem of writing data to DB twice in a short time no longer exists.
(It would write the Wrote a new workshop
activity first during transition_post_status
and then after the post is published, the Assigned presenter
is sent to DB. Previously, these two would be fired almost at the same time, causing weird behavior of notifying activity.)
I'm still curious what's the practice for us to handle such case (write DB in a row in a short time) since the logic might be changed back to use transition_post_status
.
cron job sounds like a good idea.
either find out why the timeout is occurring and solve that
What does timeout here refer to, timeout from sleep? or timeout of writing DB? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either find out why the timeout is occurring and solve that
What does timeout here refer to
I believe Alex meant rate-limit here, not timeout.
There shouldn't be any rate-limits in production that would catch this - if there is, we should probably get those lifted for self-calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep sorry Dion's right, I meant the rate limit.
|
||
foreach ($presenter_wporg_username as $username) { | ||
|
||
sleep(1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think sleep()
is a good solution in production, though it's useful for diagnosing the problem. It could theoretically lead to unexpected UI delays when publishing a post. Better to find a more robust solution: either find out why the timeout is occurring and solve that, or schedule the function to run in a cron job.
@@ -150,6 +151,71 @@ public function maybe_notify_new_published_post( $new_status, $old_status, $post | |||
$this->notify_new_blog_post( $post ); | |||
} | |||
|
|||
public function insert_post ($postId, $post) { | |||
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is REST_REQUEST
a reliable way to detect that sequence of events? And is that a common occurrence?
At a quick glance it seems some of the other notification types don't try to prevent duplicate activities when something is published twice. It might be overkill, but if it's common then as a general solution I would consider using postmeta to store a list of notified actions to prevent dupes. Perhaps that's better done on the profile API side - @dd32 do you have an opinion on this?
@@ -51,6 +51,7 @@ private function __construct() { | |||
|
|||
public function init() { | |||
add_action( 'transition_post_status', array( $this, 'maybe_notify_new_published_post' ), 10, 3 ); | |||
add_action( 'wp_insert_post', array( $this, 'insert_post' ), 10, 2 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why you used the wp_insert_post
action rather than transition_post_status
(as used by maybe_notify_new_published_post()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used transition_post_status
in the beginning, but since the action is triggered before saving data to DB, I can't get the post meta with the function get_post_meta.
The problem would be gone if transition_post_status
can be used here, are there any simple ways to get the post_meta before saving it to DB here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After thinking about it some more: you're on the right track, wp_insert_post
is (almost) the right action to use here. If it was only on transition_post_status
then we'd miss seeing presenters that were added to the post after it was published.
I think what's needed is actually the wp_insert_post_data
filter. That's triggered during wp_insert_post()
, but before the post is inserted or updated:
If you hook that one, the $postarr
array should contain all the data being inserted, including the meta_input
data that gets inserted as postmeta. And the $update
param should tell you if it's an update or an insert. So in the case of an insert, you'd add activity for all of those users. If it's an update, you could use get_post_meta()
to figure out if any new presenters are being added, and only add activity for those.
Does that make sense? I think that would mostly deal with the issue of duplicates too, since you'd only notify when a new username is found in $postarr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wp_insert_post_data
-> This is nice!
It could deal with the case:
[run1] presenter: ren -> send activity to ren
[run2] presenter: ren, ren2 -> send activity to ren2
But if it's the following case, it still duplicates, but I believe it's acceptable.
[run1] presenter: ren, ren2 -> send activity to ren, ren2
[run2] presenter: ren -> send activity to no one
[run3] presenter: ren, ren2 -> send activity to ren2 again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I agree - handling of that edge case isn't quite right, but it's good enough for now.
If we also add some basic dupe handling on the API side then that should be pretty solid. Let's make that a separate issue.
There's also the issue of removal, but since I don't think there's a delete API there's nothing we can do about it for now. We could consider handling that in a separate issue later if it becomes an issue.
f008c96
to
41ee344
Compare
Changed back to use
|
e296138
to
73cf1ae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tested, but the code LGTM 👍🏻
I left a few suggestions, but they're not blockers.
It might also help to add a case to tests/e2e.php
. I've found that easier for testing during development than doing it manually each time. It also avoids disrupting production data with testing.
...-content/plugins/wporg-profiles-wp-activity-notifier/wporg-profiles-wp-activity-notifier.php
Outdated
Show resolved
Hide resolved
...-content/plugins/wporg-profiles-wp-activity-notifier/wporg-profiles-wp-activity-notifier.php
Show resolved
Hide resolved
...-content/plugins/wporg-profiles-wp-activity-notifier/wporg-profiles-wp-activity-notifier.php
Outdated
Show resolved
Hide resolved
1e017ab
to
ced910b
Compare
ced910b
to
7ee00f4
Compare
Only change "workshop" in message but not in function name or other places as in WordPress/Learn#819, there's only text being changed. Should wait until the changes on learn side have been made before changing the remaining "workshop" here to avoid confusion.
7ee00f4
to
e85ca40
Compare
e157564
to
57c5490
Compare
Issue: WordPress/five-for-the-future#179 - Add activity when added as a presenter for Learn workshop
Question
If an author published a post, then switched back to draft, and published again, there'll be two identical activities on assigned presenters' profiles, is it expected behavior?
The icon before the assigned presenter activity is also changed as the screencast below shows, but I can't locate the
style.css
of profiles in the repo. How do we usually modify this file, do we directly modifythemes/profiles.wordpress.org/style.css
on the sandbox?Screencast of results
Screen.Capture.on.2022-07-11.at.05-02-17.mov