-
Notifications
You must be signed in to change notification settings - Fork 286
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
Expose gathering data state on page load #5933
Comments
@aaemnnosttv I've added ACs here, what do you think? I think the approach of using a transient for the temporary value vs an option for the persistent value might make sense? |
@felixarntz I've revised the AC a bit after giving this much thought. It's slightly different than we discussed recently but should be the smallest change I think. For cases where we want to know immediately if data is available, we will have a dedicated selector to use in those situations. Otherwise the existing selector will work mostly the same as today but a bit more efficiently since it won't request the report data any more once data is detected to be available. This is also rather technically detailed so there likely isn't a lot more detail to add in an IB although things like outlining how we'll clear the transient on an entity change or how the state will be passed from the server would be good to cover. Let me know what you think? |
I have added this to the User Input v2 epic, as although it is not directly related to the epic, it does block 5895 and needs to be completed for the epic to be completed. |
@felixarntz please could I chase for your review here so we can get this one moving? It is blocking several other issues so would be great to please get it over to EB ASAP. Thank you |
ACs ✅ |
@kuasha420 could we please progress the IB here as it would be ideal to get this into Sprint 90 as the last issue remaining (other than #6180 which is just for the HaTS survey) |
@kuasha420 I like the direction here 👍 I noticed you only mentioned the interface and then implement it in each of the module classes. This is why many
As a "generic" method name, I would expect this to be on a more generic interface. It probably shouldn't be part of the interface though as this is more of an implementation detail. It might make sense to include on the corresponding trait. Rather than setting the transients, it might be cleaner to have a method to get the
How about
Since this has to be dynamic to each module, I would suggest using a protected method for this instead which can live on the trait and would use
I'm not sure if
I'm not sure why this hook (and the related
This would only be relevant in Regarding tests, each interface has a corresponding set of contract tests which are defined in a trait that each module's test case Otherwise, nice work! – this is a rather complicated one! 👍 |
Thank you @aaemnnosttv for the review and valuable feedback. I have updated the IB to address your feedback and suggestions. Please feel free to have a look. Cheers! |
Thanks @kuasha420 – apologies for the delay here – this is really close, the only thing I think there is to finalize here is around the internal use of transients (methods, etc). I have a few ideas that I'll follow up with here shortly. |
After giving this some more thought, I think the simplest solution is to add a The With this added, the trait can assume transients are available like any other property on
This method name sounds generic but the usage here is specific to the transient for the data-available state. Let's name it more specifically to what it's for, perhaps
I'd like to see this implemented in a way that doesn't duplicate this across modules. This might even justify a prerequisite issue, but we do a similar thing in a few places. I'm thinking we could add a new |
QA Update:
|
@wpdarren following up on our call, I have updated the QAB to add special instruction for GA4. Cheers! |
QA Update: ✅Verified:
|
|
The changes I mentioned above turned out to be a bit more involved than anticipated (mostly regarding changes to tests) but also there were some concerns about the changes to the report-based For that reason, we've amended the initial changes here to include an expiration for the persistent gathering state to avoid permanently setting it based on a non-successful request. We'll fix this to arrive on the original permanent persistent value in #6698. Everything else is the same here and this change is essentially a one line change that can be quickly QA'd by an engineer. |
QA ✅Confirmed that the transient is set to expire in 1 hour now (matching client side storage) rather than no expiration. |
Feature Description
Until now, the concept of gathering data is something that we've calculated at runtime based on reporting data. In some cases, such as determining an initial layout it can be necessary to know whether a module is gathering data or not right away in order to avoid substantial changes as data is loaded.
While the goal is to make reporting data available right away on page load, we should do so in a way which keeps the fetching of such data async – that is, we should not be making API requests to query the gathering data state from the request serving the page itself.
Ideally this state would be available for the first page load once after module is connected, but if we can't, it should be acceptable to have the gathering state immediately available for the next page load.
As part of this issue, it would be good to revisit the concept of gathering data itself which is generally a state that a module should only be in once – regardless of how long – for a given configured entity. E.g. If a module is connected and then we detect it is no longer gathering data, it shouldn't be possible for that module to go back into a gathering data state again unless it's connected entity (i.e. data source) changed. With that in mind, every eligible module would always start in a gathering state. As soon as we're able to determine that the module is no longer in a gathering state, this would be persisted, after which we would no longer need to check. If the connection were later changed, the gathering state would be reset and the same process would repeat. This approach would be more efficient than the current implementation which only derives gathering state from requested report data (cached or freshly requested), so these queries are repeated every time the cache expires even after we detect the module is no longer gathering data.
This issue is relevant for the upcoming work for the Summary Widget (#5908) but not explicitly part of that epic.
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
googlesitekit_{$module_slug}_data_available
), as the state itself is easily recalculatable)Note: this was amended before the release to expire after 1 hour, to be addressed in Potentially incorrect data available state being persisted on temporary API error #6698
POST:data-available
module datapoint should be added for modules that expose the state*_data_available
transientisDataAvailableOnLoad
selector which should always reflect the value on page load – it should not update during the page lifecycle under normal circumstances, i.e. if data is determined to be availableinitialState
– it shouldn't be received by a resolver. For testing purposes, it could have a respective action to receive it though if useful.isGatheringData
selectors should receive corresponding state and resolvers. Selectors should be updated to return the value from state similar to other simple gettersreceiveIsGatheringData(bool)
(this can be used to simplify stories and tests for this state quite a bit but this should happen in a follow up issue)isDataAvailableOnLoad
istrue
, the state should be received asfalse
and do nothing elseisDataAvailableOnLoad
isfalse
, it should select the same report it does today, and calculate the gathering stateisGatheringData === true
, the state should receivetrue
and do nothing elseisGatheringData === false
, the state should receivefalse
AND dispatch a fetch request to persist the data availability via the new module-specific REST routePOST:modules/:identifier/data/data-available
Note that this request should only be made when data was not available on load, and was then detected to be available
Note: this may introduce failures in E2E tests due to new/unhandled fetch requests when data is available.
Implementation Brief
On PHP Side
In
Google\Site_Kit\Core\Modules/Module
class.$transients
instance variable.Google\Site_Kit\Core\Storage\Transients
instance.Create
Module_With_Data_Available_State
interface inGoogle\Site_Kit\Core\Modules
namespace.is_data_available
- returns whether thedata_available
transient is set.set_data_available
- sets thedata_available
transient.reset_data_available
- resets thedata_available
transient by deleting it.Create
Module_With_Data_Available_State_Trait
trait inGoogle\Site_Kit\Core\Modules
namespace.get_data_available_transient_name
method:googlesitekit_{$module_slug}_data_available
, replacing{$module_slug}
with$this-slug
.is_data_available
method.get
method on$this-transients
withget_data_available_transient_name()
as the first argument.set_data_available
method.set
method on$this-transients
withget_data_available_transient_name()
as the first argument andtrue
as the second argument.reset_data_available
method.delete
method on$this-transients
withget_data_available_transient_name()
as the first argument.In
Google\Site_Kit\Core\Assets\Assets
:get_inline_modules_data
method.googlesitekit_inline_modules_data
filter to an empty array and return it.get_assets
method:Script_Data
asset in the$assets
array withgooglesitekit-modules-data
handle with the following args:global
:_googlesitekitModulesData
.data_callback
: it should be a function that returns the result of$this->get_inline_modules_data()
.In
Google\Site_Kit\Core\Modules\Modules
:inline_modules_data
method:$this->get_active_modules()
.Module_With_Data_Available_State
.data_available_{$module->slug}
as key and$module->is_data_available
as value for the filtered modules.register
method:googlesitekit-modules-data
Data Script using thegooglesitekit_inline_modules_data
filter andinline_modules_data
method.In
Google\Site_Kit\Modules\Search_Console
,Google\Site_Kit\Modules\Analytics
andGoogle\Site_Kit\Modules\Analytics_4
class:Module_With_Data_Available_State
interface andModule_With_Data_Available_State_Trait
setup_assets
method:googlesitekit-modules-data
as a dependency of the modules asset.register
method:update_option_googlesitekit_{search-console/analytics/analytics-4}_settings
action to compare the current and new search console property/ga3 property/ga4 measurement id and callreset_data_available
method if they are different.get_datapoint_definitions
method:POST:data-available
definition.create_data_request
method:set_data_available
method to set thedata_available
transient.In
Google\Site_Kit\Modules\Analytics
andGoogle\Site_Kit\Modules\Analytics_4
classes:on_deactivation
method:reset_data_available
method to reset thedata_available
transient.On JS Side
In
assets/js/modules/search-console/datastore/report.js
andassets/js/modules/analytics/datastore/report.js
:_googlesitekitModulesData
to theinitialState
object.isDataAvailableOnLoad
which returns the value ofdataAvailableOnLoad
from the state.isGatheringData
selectors according to the details provided in the AC, notably:isDataAvailableOnLoad
istrue
, thenisGatheringData
should returnfalse
.gatheringDataState
by similar means as it does currently.gatheringDataState
istrue
, thenisGatheringData
should returntrue
and do nothing else.POST:data-available
using API.set() and reurnfalse
.Test Coverage
Module_With_Data_Available_State
interface.data_available
state is reset when relevant entity changes and module is deactivated.isGatheringData
to accommodate the changes.QA Brief
This is a big one and the following needs to be thoroughly tested. Although not strictly QA:Eng, an engineers' help may be needed.
isDataAvailableOnLoad
using the following browser console commands.googlesitekit.data.select('modules/search-console').isDataAvailableOnLoad()
googlesitekit.data.select('modules/analytics').isDataAvailableOnLoad()
googlesitekit.data.select('modules/analytics-4').isDataAvailableOnLoad()
false
.false
.data-available
endpoint once (for each module that is not in a gathering state).true
.isGatheringData
selector for GA4 module must be called manually on first page load to kickstart theisDataAvailableOnLoad
using the following snippet.googlesitekit.data.select('modules/analytics-4').isGatheringData();
ga4Reporting
feature flag is not enabled, theGET:report
API call will fail and theisGatheringData
will returnfalse
. So, for a more authentic experience, enable the feature flag. That way, the data available will only be persisted for sites with actual data on GA4 property.false
first time, and behave accordingly (as mentioned above) depending on the gathering data state of new property.false
and do the same as above.Changelog entry
The text was updated successfully, but these errors were encountered: