feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
_ = require ' underscore '
DatabaseStore = require ' ../../src/flux/stores/database-store '
2015-12-18 03:46:05 +08:00
DatabaseTransaction = require ' ../../src/flux/stores/database-transaction '
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
ThreadCountsStore = require ' ../../src/flux/stores/thread-counts-store '
Thread = require ' ../../src/flux/models/thread '
2016-01-26 03:35:11 +08:00
Category = require ' ../../src/flux/models/category '
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
Matcher = require ' ../../src/flux/attributes/matcher '
2015-11-25 06:41:18 +08:00
WindowBridge = require ' ../../src/window-bridge '
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
describe " ThreadCountsStore " , ->
describe " unreadCountForCategoryId " , ->
it " returns null if no count exists for the category id " , ->
expect ( ThreadCountsStore . unreadCountForCategoryId ( ' nan ' ) ) . toBe ( null )
it " returns the count plus any unsaved deltas " , ->
ThreadCountsStore._counts =
' b ' : 3
' a ' : 5
ThreadCountsStore._deltas =
' a ' : - 1
expect ( ThreadCountsStore . unreadCountForCategoryId ( ' a ' ) ) . toBe ( 4 )
expect ( ThreadCountsStore . unreadCountForCategoryId ( ' b ' ) ) . toBe ( 3 )
describe " when the mutation observer reports count changes " , ->
2015-11-25 06:41:18 +08:00
describe " in the work window " , ->
beforeEach ->
spyOn ( NylasEnv , ' isWorkWindow ' ) . andReturn ( true )
it " should merge count deltas into existing count detlas " , ->
ThreadCountsStore._deltas =
' l1 ' : - 1
' l2 ' : 2
ThreadCountsStore . _onCountsChanged ( { ' l1 ' : - 1 , ' l2 ' : 1 , ' l3 ' : 2 } )
expect ( ThreadCountsStore . _deltas ) . toEqual ( {
' l1 ' : - 2 ,
' l2 ' : 3 ,
' l3 ' : 2
} )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
2015-11-25 06:41:18 +08:00
it " should queue a save of the counts " , ->
spyOn ( ThreadCountsStore , ' _saveCountsSoon ' )
ThreadCountsStore . _onCountsChanged ( { ' l1 ' : - 1 , ' l2 ' : 1 , ' l3 ' : 2 } )
expect ( ThreadCountsStore . _saveCountsSoon ) . toHaveBeenCalled ( )
describe " in other windows " , ->
beforeEach ->
spyOn ( NylasEnv , ' isWorkWindow ' ) . andReturn ( false )
it " should use the WindowBridge to forward the invocation to the work window " , ->
spyOn ( WindowBridge , ' runInWorkWindow ' )
payload = { ' l1 ' : - 1 , ' l2 ' : 1 , ' l3 ' : 2 }
ThreadCountsStore . _onCountsChanged ( payload )
expect ( WindowBridge . runInWorkWindow ) . toHaveBeenCalledWith ( ' ThreadCountsStore ' , ' _onCountsChanged ' , [ payload ] )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
describe " when counts are persisted " , ->
it " should update it ' s _counts cache and trigger " , ->
newCounts = {
' abc ' : 1
}
spyOn ( ThreadCountsStore , ' trigger ' )
2015-12-08 08:52:46 +08:00
ThreadCountsStore . _onCountsBlobRead ( newCounts )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
expect ( ThreadCountsStore . _counts ) . toEqual ( newCounts )
expect ( ThreadCountsStore . trigger ) . toHaveBeenCalled ( )
describe " _fetchCountsMissing " , ->
beforeEach ->
ThreadCountsStore._categories = [
2016-01-26 03:35:11 +08:00
new Category ( id: " l1 " , name: " inbox " , displayName: " Inbox " , accountId: ' a1 ' ) ,
new Category ( id: " l2 " , name: " archive " , displayName: " Archive " , accountId: ' a1 ' ) ,
new Category ( id: " l3 " , displayName: " Happy Days " , accountId: ' a1 ' ) ,
new Category ( id: " l4 " , displayName: " Sad Days " , accountId: ' a1 ' )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
]
2015-11-25 06:41:18 +08:00
ThreadCountsStore._deltas =
l1: 10
l2: 0
l3: 3
l4: 12
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
ThreadCountsStore._counts =
l1: 10
l2: 0
2015-11-25 06:41:18 +08:00
@countResolve = null
@countReject = null
spyOn ( ThreadCountsStore , ' _fetchCountForCategory ' ) . andCallFake =>
new Promise (resolve, reject) =>
@countResolve = resolve
@countReject = reject
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
it " should call _fetchCountForCategory for the first category not already in the counts cache " , ->
ThreadCountsStore . _fetchCountsMissing ( )
calls = ThreadCountsStore . _fetchCountForCategory . calls
expect ( calls . length ) . toBe ( 1 )
expect ( calls [ 0 ] . args [ 0 ] ) . toBe ( ThreadCountsStore . _categories [ 2 ] )
2015-11-25 06:41:18 +08:00
it " should set the _deltas for the category it ' s counting back to zero " , ->
ThreadCountsStore . _fetchCountsMissing ( )
expect ( ThreadCountsStore . _deltas . l3 ) . toBe ( 0 )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
2015-11-25 06:41:18 +08:00
describe " when the count promise finishes " , ->
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
it " should add it to the count cache " , ->
ThreadCountsStore . _fetchCountsMissing ( )
advanceClock ( )
@ countResolve ( 4 )
advanceClock ( )
2015-11-25 06:41:18 +08:00
expect ( ThreadCountsStore . _counts . l3 ) . toEqual ( 4 )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
it " should call _fetchCountsMissing again to populate the next missing count " , ->
ThreadCountsStore . _fetchCountsMissing ( )
spyOn ( ThreadCountsStore , ' _fetchCountsMissing ' )
advanceClock ( )
@ countResolve ( 4 )
advanceClock ( )
2015-11-25 08:16:58 +08:00
advanceClock ( 10001 )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
expect ( ThreadCountsStore . _fetchCountsMissing ) . toHaveBeenCalled ( )
2015-11-25 06:41:18 +08:00
describe " when deltas appear during a count " , ->
it " should not set the count and count again in 10 seconds " , ->
ThreadCountsStore . _fetchCountsMissing ( )
spyOn ( ThreadCountsStore , ' _fetchCountsMissing ' )
advanceClock ( )
ThreadCountsStore._deltas.l3 = - 1
@ countResolve ( 4 )
advanceClock ( )
expect ( ThreadCountsStore . _counts . l3 ) . toBeUndefined ( )
expect ( ThreadCountsStore . _fetchCountsMissing ) . not . toHaveBeenCalled ( )
advanceClock ( 10001 )
expect ( ThreadCountsStore . _fetchCountsMissing ) . toHaveBeenCalled ( )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
describe " when a count fails " , ->
it " should not immediately try to count any other categories " , ->
feat(tasks): add Create, Update, Destroy tasks plus spec & lint fixes
Summary:
1. **Generic CUD Tasks**: There is now a generic `CreateModelTask`,
`UpdateModelTask`, and `DestroyModelTask`. These can either be used as-is
or trivially overridden to easily update simple objects. Hopefully all of
the boilerplate rollback, error handling, and undo logic won't have to be
re-duplicated on every task. There are also tests for these tasks. We use
them to perform mutating actions on `Metadata` objects.
1. **Failing on Promise Rejects**: Turns out that if a Promise rejected
due to an error or `Promise.reject` we were ignoring it and letting tests
pass. Now, tests will Fail if any unhandled promise rejects. This
uncovered a variety of errors throughout the test suite that had to be
fixed. The most significant one was during the `theme-manager` tests when
all packages (and their stores with async DB requests) was loaded. Long
after the `theme-manager` specs finished, those DB requests were
(somtimes) silently failing.
1. **Globally stub `DatabaseStore._query`**: All tests shouldn't actually
make queries on the database. Furthremore, the `inTransaction` block
doesn't resolve at all unless `_query` is stubbed. Instead of manually
remembering to do this in every test that touches the DB, it's now mocked
in `spec_helper`. This broke a handful of tests that needed to be manually
fixed.
1. **ESLint Fixes**: Some minor fixes to the linter config to prevent
yelling about minor ES6 things and ensuring we have the correct parser.
Test Plan: new tests
Reviewers: bengotow, juan, drew
Differential Revision: https://phab.nylas.com/D2419
Remove cloudState and N1-Send-Later
2016-01-05 08:39:14 +08:00
spyOn ( console , " warn " )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
ThreadCountsStore . _fetchCountsMissing ( )
spyOn ( ThreadCountsStore , ' _fetchCountsMissing ' )
spyOn ( console , ' error ' )
advanceClock ( )
@ countReject ( new Error ( " Oh man something really bad. " ) )
advanceClock ( )
feat(tasks): add Create, Update, Destroy tasks plus spec & lint fixes
Summary:
1. **Generic CUD Tasks**: There is now a generic `CreateModelTask`,
`UpdateModelTask`, and `DestroyModelTask`. These can either be used as-is
or trivially overridden to easily update simple objects. Hopefully all of
the boilerplate rollback, error handling, and undo logic won't have to be
re-duplicated on every task. There are also tests for these tasks. We use
them to perform mutating actions on `Metadata` objects.
1. **Failing on Promise Rejects**: Turns out that if a Promise rejected
due to an error or `Promise.reject` we were ignoring it and letting tests
pass. Now, tests will Fail if any unhandled promise rejects. This
uncovered a variety of errors throughout the test suite that had to be
fixed. The most significant one was during the `theme-manager` tests when
all packages (and their stores with async DB requests) was loaded. Long
after the `theme-manager` specs finished, those DB requests were
(somtimes) silently failing.
1. **Globally stub `DatabaseStore._query`**: All tests shouldn't actually
make queries on the database. Furthremore, the `inTransaction` block
doesn't resolve at all unless `_query` is stubbed. Instead of manually
remembering to do this in every test that touches the DB, it's now mocked
in `spec_helper`. This broke a handful of tests that needed to be manually
fixed.
1. **ESLint Fixes**: Some minor fixes to the linter config to prevent
yelling about minor ES6 things and ensuring we have the correct parser.
Test Plan: new tests
Reviewers: bengotow, juan, drew
Differential Revision: https://phab.nylas.com/D2419
Remove cloudState and N1-Send-Later
2016-01-05 08:39:14 +08:00
expect ( console . warn ) . toHaveBeenCalled ( )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
expect ( ThreadCountsStore . _fetchCountsMissing ) . not . toHaveBeenCalled ( )
describe " _fetchCountForCategory " , ->
2016-01-26 03:35:11 +08:00
it " should make the appropriate category database query " , ->
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
spyOn ( DatabaseStore , ' count ' )
Matcher.muid = 0
2016-01-26 03:35:11 +08:00
ThreadCountsStore . _fetchCountForCategory ( new Category ( id: ' l1 ' , accountId: ' a1 ' ) )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
Matcher.muid = 0
expect ( DatabaseStore . count ) . toHaveBeenCalledWith ( Thread , [
2016-01-26 03:35:11 +08:00
Thread . attributes . categories . contains ( ' l1 ' ) ,
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
Thread . attributes . accountId . equal ( ' a1 ' ) ,
Thread . attributes . unread . equal ( true ) ,
] )
describe " _saveCounts " , ->
beforeEach ->
ThreadCountsStore._counts =
' b ' : 3
' a ' : 5
ThreadCountsStore._deltas =
' a ' : - 1
' c ' : 2
it " should merge the deltas into the counts and reset the deltas, ignoring any deltas for which the initial count has not been run " , ->
ThreadCountsStore . _saveCounts ( )
expect ( ThreadCountsStore . _counts ) . toEqual ( {
' b ' : 3
' a ' : 4
} )
it " should persist the new counts to the database " , ->
2015-12-18 03:46:05 +08:00
spyOn ( DatabaseTransaction . prototype , ' persistJSONBlob ' )
runs =>
ThreadCountsStore . _saveCounts ( )
waitsFor =>
DatabaseTransaction . prototype . persistJSONBlob . callCount > 0
runs =>
expect ( DatabaseTransaction . prototype . persistJSONBlob ) . toHaveBeenCalledWith ( ThreadCountsStore . JSONBlobKey , ThreadCountsStore . _counts )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
describe " CategoryDatabaseMutationObserver " , ->
beforeEach ->
2016-01-26 03:35:11 +08:00
@category1 = new Category ( id: " l1 " , name: " inbox " , displayName: " Inbox " )
@category2 = new Category ( id: " l2 " , name: " archive " , displayName: " Archive " )
@category3 = new Category ( id: " l3 " , displayName: " Happy Days " )
@category4 = new Category ( id: " l4 " , displayName: " Sad Days " )
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
2016-01-26 03:35:11 +08:00
# Values here are the "after" state. Below, the spy on the query returns the
# "current" state.
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
@threadA = new Thread
id: " A "
unread: true
2016-01-26 03:35:11 +08:00
categories: [ @ category1 , @ category4 ]
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
@threadB = new Thread
id: " B "
unread: true
2016-01-26 03:35:11 +08:00
categories: [ @ category3 ]
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
@threadC = new Thread
id: " C "
unread: false
2016-01-26 03:35:11 +08:00
categories: [ @ category1 , @ category3 ]
feat(counts): Unread counts for all folders and labels across all accounts
Summary:
This diff replaces the UnreadCountStore with a better approach that is able to track unread counts for all folders/labels without continuous (and cripplingly slow) SELECT COUNT(*) queries.
When models are written to the database, we currently don't send out notifications with the "previous" state of those objects in the database. This makes it hard to determine how to update counters. (In the future, we may need to do this for live queries). Unfortunately, getting the "previous" state is going to be very hard, because multiple windows write to the database and the "previous" state we have might be outdated. We'd almost have to run a "SELECT" right before every "REPLACE INTO".
I created an API that allows you to register observers around persistModel and unpersistModel. With this API, you can run queries before and after the database changes are made and pluck just the "before" state you're interested in.
The `ThreadCountsStore` uses this API to determine the impact of persisting a set of threads on the unread counts of different labels. Before the threads are saved, it says "how much do these thread IDs contribute to unread counts currently?". After the write is complete it looks at the models and computes the difference between the old count impact and the new count impact, and updates the counters.
I decided not to attach the unread count to the Label objects themselves because 1) they update frequently and 2) most things observing the DatabaseStore for categories do not care about counts, so they would be updating unnecessarily.
The AccountSidebar now listens to the ThreadCountsStore as well as the CategoryStore, and there's a new preference in the General tab for turning off the counts.
Test Plan: Tests are a work in progress, want to get feedback first!
Reviewers: juan, evan
Reviewed By: evan
Differential Revision: https://phab.nylas.com/D2232
2015-11-24 09:12:22 +08:00
describe " given a set of modifying models " , ->
2015-12-05 08:29:26 +08:00
scenarios = [ {
type: ' persist ' ,
expected: {
l3: - 1 ,
l2: - 1 ,
l4: 1
}
} , {
type: ' unpersist ' ,
expected: {
l1: - 1 ,
l3: - 2 ,
l2: - 1
}
} ]
scenarios . forEach ({type, expected}) ->
2016-01-26 03:35:11 +08:00
it " should call countsDidChange with the category membership deltas ( #{ type } ) " , ->
2015-12-05 08:29:26 +08:00
queryResolves = [ ]
query = jasmine . createSpy ( ' query ' ) . andCallFake =>
new Promise (resolve, reject) ->
queryResolves . push ( resolve )
countsDidChange = jasmine . createSpy ( ' countsDidChange ' )
m = new ThreadCountsStore . CategoryDatabaseMutationObserver ( countsDidChange )
beforePromise = m . beforeDatabaseChange ( query , {
type: type
objects: [ @ threadA , @ threadB , @ threadC ] ,
objectIds: [ @ threadA . id , @ threadB . id , @ threadC . id ]
objectClass: Thread . name
} )
2016-01-26 03:35:11 +08:00
expect ( query . callCount ) . toBe ( 1 )
expect ( query . calls [ 0 ] . args [ 0 ] ) . toEqual ( " SELECT `Thread`.id as id, `Thread-Category`.`value` as catId FROM `Thread` INNER JOIN `Thread-Category` ON `Thread`.`id` = `Thread-Category`.`id` WHERE `Thread`.id IN ( ' A ' , ' B ' , ' C ' ) AND `Thread`.unread = 1 " )
2015-12-05 08:29:26 +08:00
queryResolves [ 0 ] ( [
2016-01-26 03:35:11 +08:00
{ id: @ threadA . id , catId: @ category1 . id } ,
{ id: @ threadA . id , catId: @ category3 . id } ,
{ id: @ threadB . id , catId: @ category2 . id } ,
{ id: @ threadB . id , catId: @ category3 . id } ,
2015-12-05 08:29:26 +08:00
] )
waitsForPromise =>
beforePromise . then (result) =>
expect ( result ) . toEqual ( {
categories: {
l1: - 1 ,
l3: - 2 ,
l2: - 1
}
} )
m . afterDatabaseChange ( query , {
type: type
objects: [ @ threadA , @ threadB , @ threadC ] ,
objectIds: [ @ threadA . id , @ threadB . id , @ threadC . id ]
objectClass: Thread . name
} , result )
expect ( countsDidChange ) . toHaveBeenCalledWith ( expected )