Two things requested:
- Make read() return a traversable object instead of an array (better resource usage. See below for story.)
- Change arguments of crud functions as follows:
create($entity, $fields(config objects)) -> ($entity, $field_names*) update($comment) -> ($entity, $field_names*) read($entities, $entity_type, $accurate*) -> ($entity_type, $entities, $field_names*, $accurate*) delete($entity) -> ($entity, $field_names*) larowlan #8: add deleteMultiple($entity_type, $entity_ids, $field_names*) (* = optional. $entity means 'commented/parent entity'.)
We can still clean up the interface now because it's fresh enough that noone 'external' is using it yet.
Beta phase evaluation
| Issue category | Task because it makes the code more performant and improves the interface |
|---|---|
| Unfrozen changes | Unfrozen because it only changes an interface that is unlikely to be used outside of core comment module |
| Prioritized changes | The main goal of this issue is performance |
| Disruption | Not disruptive for core/contributed and custom modules/themes because it is unlikely to be used outside core comment module - possibly only in MongoDb |
Justification
Constraints imposed by practical usage
- read() is the most important method in this service and should keep an array as the first argument for speed. (Each time I look at this I want to change ($entities, $entity_type) to ($entity_ids, $entity_type) to make things less redundant... but then I see the definition of hook_entity_storage_load(). So I have no opinion on that.)
- CommentStatistics::update() inserts a record if one does not exist. That means we cannot, at the moment, delete statistics records for an entity before deleting its comments; that would recreate the record.
Detailed changes
- read - adding $field_names: it's quite possible that someone making a website with multiple comment fields, wants to read (maybe a lot of) statistics for only one of the fields. Also: DX/the presence of this parameter implicitly reminds you that the return value can hold multiple records for the same entity. (Forgetting this led to my mess-up re #1.)
- delete/update - adding $feld_names: it's possible that you only want to delete records for one field name as well. Adding it to update() isn't that important, but: adds consistency (DX).
- create - replacing the field-definition-config objects by their machine names: for unification with other methods, and because it's highly unlikely any service implementation will need the objects. (The current code does not use them.)
- create - making the field_names optional: because we can; because of consistency with other methods and we don't want to make it required on all the methods, that would be a pain.
- update - changing to ($entity, $field_names): because of consistency; from a code perspective there is no reason why this method should have different arguments than create(); also, having $comment falsely gives the impression that you should call this method for each comment individually, if you do mass operations (e.g. delete) on comments attached to the same entity.
- delete these comments are superseded by larowlan's #8 suggestion; ...I'm not sure about this. It seems like
- we will at some point want to be able to delete all the records for an entity_type + field_name combination, i.e. for all entities. This patch doesn't actually implement that; it just makes it so you could implement something special like e.g. array(0) to mean "all entities".
- loading full entities in order to delete related data, seems a bit strange. (In comment_field_instance_config_delete(), we would not have the entities yet, only the IDs from an EntityQuery.)
But if anyone wants to keep the method signature to ($entity, $field_names), I'll change that back.
Patch details
- The change in update() adds a 10-line code block + a foreach that starts with a 3-line if{}, near the top. The rest of the code didn't change, it was just indented.
- The test: I found working code that mocked 'iterator methods' on http://stackoverflow.com/questions/15907249/mocking-an-iterator-class-wi..., and not inside the D8 source code, so copied it. Without changing, so it's 'too complete' now. I have no idea if that can be done better, so have at it if you want.
- CommentStatisticsInterface::read() adds back some comments deleted from CommentStorageInterface::updateEntityStatistics() by #2280861: CommentStatistics service followup.
Remaining tasks
Make CommentStatistics language aware, as noted around #2428795-94: Translatable entity 'changed' timestamps are not working at all. This should be done in a new issue.
Original issue text / point 1
Earlier, I filed an issue #2259209: Fix CommentStatistics::read() because I wanted read() to return an array like the interface documentation said it does.
Well, that was kinda silly. Since I was keying the array by entity_id, it led to the bug which is solved by #2292115: Comment statistics is no correctly loaded into entity object if more than 1 comments field.
Unfortunately I did not see that last issue until it was fixed. Because
- returning a non-keyed array has no real advantage over returning an iterator
- returning an array takes more processing power and memory (it's conceivable that you want to get a lot of statistics data
...so I'd like to restore the situation to before these two issues were applied :-p ...except the interface documentation should be amended. Right now, we can still be sure we can change the interface without penalty.
| Comment | File | Size | Author |
|---|---|---|---|
| #55 | 2318875-nr-bot.txt | 151 bytes | needs-review-queue-bot |
| #37 | comment-statistics-2318875-37.patch | 31.93 KB | roderik |
Comments
Comment #1
roderikComment #2
roderiktest cleanup
Comment #3
roderikSeparate issue (but merged into here anyway)
(Let me know if you like #2 but not this addition / you like them separated.)
While coding, It occurred to me that
So I'm requesting these things be added as method arguments. Also, unify create: $fields has no use, we can make it just $field_names without problem.
TODO: make tests. (I need someone to at least say yes before I do this ;) )
** "hey wait a minute", TODO: check what happens right now when one comment field is deleted. Are statistics deleted? Of one field only?
Comment #4
roderikAdded typehint, from review dawehner in #2280861-18: CommentStatistics service followup
Comment #5
roderikpreempting testbot fail now #2280861 is in, will reroll (may take some days)
Comment #6
roderik"a few days", oops...
Rerolled. I hope we can get this interface change in soon - theoretically it's now a compatibility break with what was committed 18 days ago...
Comment #7
roderik...and while I was writing a summary 2 weeks ago, I stumbled into a question. And another issue.
Now, my proposal has grown into a fuller interface overhaul. Changed summary.
Comment #8
larowlanLets leave this for the dedicated issue
this feels to me like we need both a delete (as in HEAD) and a deleteMultiple (as per this patch)
maybe merge this with the
// Skip fields that entity does not havecomment lower down?same?
Needs (optional) at start.
This is awesome - should be part of UnitTestCase so other modules/tests can use it.
Comment #10
roderikdeleteMultiple: ha, good one - then also developers won't get the delete() signature wrong.
Implemented with NULL meaning 'any', as e.g. Entity::loadMultiple() does.
(If read() should now be readMultiple, I'll hear it - I have no opinion.)
(Plus copypasted some getMock() / expects() stuff for the test bot.)
Comment #12
andypostif this changing now, lets move entity_type before IDs
Any reason for this method? no usage...
Comment #13
roderikOK, but then let's do read() too. I like it this way better too, though it differs from the order in hook_entity_storage_load(etc) which calls CommentStatistics::read()...
There will be usage: #2338457-7: comment_field_config_delete() does not delete comments (also see review block 8.1 above)
Further, the test failures in #10 which are a bit worrying. From the interdiff:
This is a bugfix (buggy code inserted by me in #2068331: Convert comment SQL queries to the Entity Query API). $latest_comment was an array of arrays, is now a database statement-result-thingy, $latest_comment->last_comment_timestamp also did not exist before the fix but still the test did not throw errors.
This is to shut up test migrations. These can in some cases insert 'stub entities' - which do not have an entity_id.
It feels like a cop out because it's not wrong for this code to assume that an entity_id always exists on postSave. (Or is it?)
I have an idea that Migrate will run into similar issues, and how it should be fixed (I will have a try at it), but I might be totally wrong... so for now, this seemed like the most practical thing to do.
Comment #15
roderiksearch/replace fail
Comment #16
roderikComment #17
larowlanComment #18
larowlanThis doesn't seem to be optional - so passing an empty array here (which will return FALSE) will delete all records? That seems wrong.
Not seeing any test coverage for this
Comment #19
larowlanComment #20
roderik18.1 actually I think we want to be able to return 'all records' (at least for a certain field name), for cleanup. But I now made it such that you need to actively pass NULL for that.
(Which now makes it do what the interface spec actually said. Which is almost but not fully to Entity::loadMultiple() calls, because NULL is the default value there and cannot be actively passed to the function.)
18.2 OK, added some test. (Plus deleted an almost-unrelated Comment::load() call which really is not necessary.)
Note: first hunk of the interdiff only reverts a change present in patch #15.
Comment #22
andypostCurrent code affected too, filed #2422443: Fix default value of author in \Drupal\comment\CommentStatistics::create()
this is a current bug in code, just copy/paste.
$last_comment_id never get current user ID
Comment #23
roderikFairly trivial reroll. It will probably fail as andypost indicated in #22, but at least it's rerolled. Let the testbot tell whether anything else is off.
Comment #25
andypostFailed with
Undefined property: Drupal\comment\Tests\CommentStatisticsTest::$web_userDrupal\comment\Tests\CommentStatisticsTest->testCommentNodeCommentStatistics() Drupal\simpletest\TestBase->run(Array) simpletest_script_run_one_test('116', 'Drupal\comment\Tests\CommentStatisticsTest') Notice CommentStatisticsTest.php 122Comment #26
andypostplease remove this line
Comment #27
roderik@ #25:
Yes, I should have tested this old issue locally first. Interdiff does
@ #26:
You already made a new issue for that. You are right these need unit tests (I'll try to work on them). But let's then fix this bug (delete this line) in that issue.
Comment #28
andypostAnther round on review, mostly to follow 8.x.
2 places uses same code - there's comment manager getFields() method for that
just needs ELSE
Request time should be taken from server vars, to allow unit-testing https://www.drupal.org/node/2463059
Comment #29
roderikReroll and incorporated points #1 / #3 above.
For #2, there is #2422443: Fix default value of author in \Drupal\comment\CommentStatistics::create().
A @todo was inserted mentioning this issue. (ref: #2428795-94: Translatable entity 'changed' timestamps are not working at all.) IMHO his should be done in a separate issue, however. (It needs adjustments to the storage schema.) So I removed the issue number from the code.
Comment #30
roderik.
Comment #32
roderikGreat, my small change to Comment::postSave again uncovers a seemingly unrelated bug in a Migrate test.
I'll let the testbot work for me. If this goes green, I'll probably split the interdiff out into a separate issue and come up with a good description.
Comment #35
roderikMigrateDrupal6TestBase has changed. So: undoing the interdiff from #32 and letting the testbot decide if there are still not-directly-related failures here.
Comment #37
roderikOK good - the changes to core simplify this patch a little bit.
Now the unrelated test failure (in migrate) has gone away, we are back to the situation in #29.
With, obviously, the added difficulty that APIs are frozen. So this may be left untouched for a long time. (I guess that's a point that will be addressed in other comment related issues as well, so just waiting for the outcome of those...)
Comment #38
andypostqueued to test with postgres
in general changes makes sense, API changes could be minified but anyway requires BC to be commited in 8.x minors
OTOH we need to solve related #2495087: comment_entity_storage_load() is too expensive on cold caches first, to make sure that we have optimal statistics loading, then decide which arguments are really needed for the service
Also we can add new implementation of service with different name and leave BC wrapper in old service
Comment #40
andypostComment #53
andypostif we change interface then better to pass request object here (with fallback to \Drupal::request()
it got rework in #2422443: Fix default value of author in \Drupal\comment\CommentStatistics::create()
Comment #55
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.