Skip to content
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

Add notification tags #768

Merged
merged 4 commits into from
Mar 28, 2017
Merged

Add notification tags #768

merged 4 commits into from
Mar 28, 2017

Conversation

nikitin-da
Copy link
Collaborator

Closes: #663

@codecov-io
Copy link

codecov-io commented Feb 26, 2017

Codecov Report

Merging #768 into master will increase coverage by 0.79%.
The diff coverage is 96.89%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #768      +/-   ##
==========================================
+ Coverage   96.05%   96.85%   +0.79%     
==========================================
  Files          87       87              
  Lines        2460     2638     +178     
  Branches      267      296      +29     
==========================================
+ Hits         2363     2555     +192     
+ Misses         68       50      -18     
- Partials       29       33       +4
Impacted Files Coverage Δ
.../com/pushtorefresh/storio/sqlite/StorIOSQLite.java 100% <100%> (ø) ⬆️
...shtorefresh/storio/sqlite/queries/DeleteQuery.java 100% <100%> (ø) ⬆️
...qlite/operations/delete/DefaultDeleteResolver.java 100% <100%> (ø) ⬆️
...shtorefresh/storio/sqlite/queries/InsertQuery.java 100% <100%> (ø) ⬆️
...torio/sqlite/operations/put/PreparedPutObject.java 96.87% <100%> (+3.77%) ⬆️
...com/pushtorefresh/storio/sqlite/queries/Query.java 100% <100%> (+2.06%) ⬆️
.../pushtorefresh/storio/sqlite/queries/RawQuery.java 100% <100%> (ø) ⬆️
...pushtorefresh/storio/internal/InternalQueries.java 100% <100%> (ø) ⬆️
...efresh/storio/sqlite/operations/put/PutResult.java 100% <100%> (ø) ⬆️
.../java/com/pushtorefresh/storio/sqlite/Changes.java 100% <100%> (ø) ⬆️
... and 29 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2218a19...f2b48a3. Read the comment docs.

Copy link
Member

@artem-zinnatullin artem-zinnatullin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few design questions, otherwise LGTM!

@@ -36,7 +62,7 @@ private Changes(@NonNull Set<String> affectedTables) {
*/
@NonNull
public static Changes newInstance(@NonNull Set<String> affectedTables) {
return new Changes(affectedTables);
return new Changes(affectedTables, Collections.<String>emptySet());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg, this looks so weird after almost year of writing in kotlin style Collections.emptySet<String>(). I haven't been really writing in java for a long time now…

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😿

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Changes changes = (Changes) o;

return affectedTables.equals(changes.affectedTables);
if (!affectedTables.equals(changes.affectedTables)) return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad we have EqualsVerifier!

@@ -144,6 +145,110 @@
}

/**
* Allows observe changes of required tags.
* <p/>
* Tags are the addition level of notifications that provides
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tags are optional meta information that you can attach to Changes object to have more fine-grained control over observing changes in the database.?

* Immutable set of affected tags.
*/
@NonNull
private final Set<String> affectedTags;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, what if we make Set<Object> affectedTags? Or that would be overkill?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I will be less convenient for the most frequent case with Strings.
But I agree tags it is not about common cases, so flexibility should be the main purpose.
@rsinukov also votes for object.
Let's do it=)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I do agree that Strings will probably be most used and we'll have to force these users to class-cast them for no good reason, let's wait for @geralt-encore opinion then!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for Object. In my understanding, you can use as tag whatever you want and if String will be the most frequently used it doesn't mean that tag should be restricted to it. Also, View tag in Android is Object as well.

return observeChangesOfTags(Collections.singleton(tag));
}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el

* @return {@link rx.Observable} of {@link Changes} subscribed to changes of required tags.
*/
@NonNull
public abstract Observable<Changes> observeChangesOfTablesAndTags(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need combination methods, user can observe raw changes and filter whatever combination he/she needs (using RxJava, plain java, etc)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, we should open ChangesFilter to make it visible for Query

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets make it public and keep comment that it is for internal usage only?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep as small amount of public methods/classes/API as possible if current ones already allow you to do what you want without too much boilerplate…

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for removing it. It can get out of hands pretty quick if we need to introduce one more way of filtering changes. observeChangesOfTablesAndTagsAndWhatever plus combination look ugly.

* @return {@link rx.Observable} of {@link Changes} subscribed to changes of required tag.
*/
@NonNull
public Observable<Changes> observeChangesOfTableAndTag(@NonNull String table, @NonNull String tag) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above?

* @see com.pushtorefresh.storio.sqlite.StorIOSQLite#observeChangesOfTag(String)
*/
@NonNull
public CompleteBuilder tag(@Nullable String tag) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tags? or overload with Set<String>? Same for other queries

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -65,6 +65,16 @@ public void observesTablesShouldNotBeNull() {
}

@Test
public void observesTagsShouldNotBeNull() {
RawQuery rawQuery = RawQuery.builder()
.query("lalala I know SQL")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kek

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nobody knows!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't tell @thevery and Stasic! (If you see this message it's a GitHub's bug obviously).

Copy link
Collaborator

@geralt-encore geralt-encore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! 👍

* Immutable set of affected tags.
*/
@NonNull
private final Set<String> affectedTags;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for Object. In my understanding, you can use as tag whatever you want and if String will be the most frequently used it doesn't mean that tag should be restricted to it. Also, View tag in Android is Object as well.

return new Changes(Collections.singleton(affectedTable));
final Set<String> tags = affectedTag == null
? Collections.<String>emptySet()
: singleton(affectedTag);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to reuse static import for singleton next line or remove it completely.

* @return {@link rx.Observable} of {@link Changes} subscribed to changes of required tags.
*/
@NonNull
public abstract Observable<Changes> observeChangesOfTablesAndTags(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for removing it. It can get out of hands pretty quick if we need to introduce one more way of filtering changes. observeChangesOfTablesAndTagsAndWhatever plus combination look ugly.

@geralt-encore
Copy link
Collaborator

@nikitin-da just one comment. I think that it might be a good idea to change signature of varargs methods which are part of public API to T firstTag, T... tags instead of just T...tags since with current implementation it is possible to forget to provide any tags which lead to very obscure bugs for users.

@nikitin-da
Copy link
Collaborator Author

@geralt-encore good idea!
For queries it will be quite simple (if someone will decided to reuse existed builder and clear tags, he can call tags((Collection<?>) null)).
But for changes and operation results it will increase overloaded methods =(
We can't remove methods with signature like newInstance(@NonNull Set<String> affectedTables) in minor release, because it is breaking change.
And creating separate method will increase class complexity (PutResult now 8 methods ->will be 12 😿 )
@artem-zinnatullin, what is your opinion?


final Observable<Object> observable;
if (!observesTables.isEmpty() || !observesTags.isEmpty()) {
observable = ChangesFilter.applyForTablesAndTags(storIOSQLite.observeChanges(), observesTables, observesTags)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@artem-zinnatullin It seems we forgot to subscribe on changes here =(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct me if I'm wrong, but it was our design decision, since executeSql is basically a side effect and does not return data from database, same as we do for Put and Delete, we don't subscribe them to db changes!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I agree that it is the side effect operation and it will not be clean to subscribe on some changes with it.
But current RawQuery.observesTags possibility can be misleading.
Maybe we should note this feature in doc, because it may look as unexpected behavior =(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I definitely remember discussing that, and I'm pretty sure we have docs about it :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find it for asRxObservable, for RawQuery and in the doc too=)

@nikitin-da
Copy link
Collaborator Author

@artem-zinnatullin PTAL please, to prevent guys from merge conflicts ;)

Copy link
Member

@artem-zinnatullin artem-zinnatullin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExecuteSql should not observe changes in db! Otherwise LGTM, though I kinda liked idea of String tags since they're easier to use and understand cc @thevery do you have an opinion here?

@@ -16,28 +17,62 @@
* <p>
* Hides RxJava from ClassLoader via separate class.
*/
final class ChangesFilter implements Func1<Changes, Boolean> {
public final class ChangesFilter implements Func1<Changes, Boolean> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't keep it package private?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because it used in com.pushtorefresh.storio.sqlite.impl for DefaultStorIOSQLite#observeChangesInTables and com.pushtorefresh.storio.sqlite.operations.execute for asRxObservable


final Observable<Object> observable;
if (!observesTables.isEmpty() || !observesTags.isEmpty()) {
observable = ChangesFilter.applyForTablesAndTags(storIOSQLite.observeChanges(), observesTables, observesTags)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct me if I'm wrong, but it was our design decision, since executeSql is basically a side effect and does not return data from database, same as we do for Put and Delete, we don't subscribe them to db changes!

@thevery
Copy link

thevery commented Mar 13, 2017

@artem-zinnatullin objects are easier to fail (hashCode/equals override) and I don't know useful examples of objects instead of strings, especially with the possibility to pass several tags.

@artem-zinnatullin
Copy link
Member

Yeah, I have similar thoughts, moreover, string tags can be more understandable for those who remember how web 2.0 was growing: tag clouds on websites, tags in blog posts/articles, tags in twitter and so on. @geralt-encore?

@nikitin-da
Copy link
Collaborator Author

nikitin-da commented Mar 14, 2017

It seem there is equality of votes for now, so what type of tag will be final?)
@geralt-encore, @rsinukov, @StanisVS voted for objects 🎉 ,
@artem-zinnatullin and @thevery and I - strings ❤️

@nikitin-da
Copy link
Collaborator Author

There was also question about first required tag with vararg #768 (comment)
@artem-zinnatullin what is your opinion?

@artem-zinnatullin
Copy link
Member

@nikitin-da I've changed emojis to ❤️ and 🎉 to remove negativity of 👎 variant haha, so please ask guys from your team to vote here so we could count here, cc @geralt-encore, I'll also ask community to vote.

Regarding overloads — I like @geralt-encore's suggestion about T tag, T… otherTags, so if that seems possible now (since we decided to remove observeChangesOfTablesAndTags() — let's implement that for methods that accept tags only. I didn't really get the note about removingnewInstance(@NonNull Set<String> affectedTables), sorry…

@nikitin-da
Copy link
Collaborator Author

nikitin-da commented Mar 18, 2017

String variant won 6:5 )

@nikitin-da nikitin-da merged commit f6f35fe into master Mar 28, 2017
@nikitin-da nikitin-da deleted the issue-663 branch March 28, 2017 05:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants