File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -27,12 +27,13 @@ module.exports = async function (req, res) {
2727 }
2828 const shouldIncrement = query . inc !== 'false' && query . inc !== false
2929 try {
30+ const currentViews = db . has ( pathname ) ? db . get ( pathname ) . views . length : 0
3031 // Add a view and send the total views back to the client
3132 if ( shouldIncrement ) {
32- await pushView ( pathname , { time : Date . now ( ) } )
33+ pushView ( pathname , { time : Date . now ( ) } )
3334 }
3435 if ( req . method === 'GET' ) {
35- send ( res , 200 , { views : db . has ( pathname ) ? db . get ( pathname ) . views . length : 0 } )
36+ send ( res , 200 , { views : shouldIncrement ? currentViews + 1 : currentViews } )
3637 } else {
3738 send ( res , 200 )
3839 }
Original file line number Diff line number Diff line change @@ -4,9 +4,9 @@ const db = require('./db')
44// db messing up.
55const pushView = async ( key , view ) => {
66 const locks = { }
7- await push ( )
7+ push ( )
88
9- async function push ( ) {
9+ function push ( ) {
1010 if ( locks [ key ] ) return setImmediate ( push )
1111 locks [ key ] = true
1212
@@ -18,9 +18,13 @@ const pushView = async (key, view) => {
1818 }
1919
2020 try {
21- await db . put ( key , { views : views . concat ( [ view ] ) } )
22- delete locks [ key ]
21+ db . put ( key , { views : views . concat ( [ view ] ) } )
22+ . then ( ( ) => {
23+ delete locks [ key ]
24+ } )
25+ . catch ( err => { throw err } )
2326 } catch ( err ) {
27+ delete locks [ key ]
2428 throw err
2529 }
2630 }
Original file line number Diff line number Diff line change 1+ const request = require ( 'request-promise' )
2+ const { listen, mockDb } = require ( './utils' )
3+
4+ jest . mock ( '../src/db' , ( ) => mockDb )
5+ const service = require ( '../src' )
6+ let url
7+
8+ beforeEach ( async ( ) => {
9+ url = await listen ( service )
10+ mockDb . _setDelay ( 10 )
11+ } )
12+
13+ afterEach ( async ( ) => {
14+ mockDb . _reset ( )
15+ mockDb . _setDelay ( )
16+ } )
17+
18+ it ( 'should atomically set two views coming in at the same time' , async ( ) => {
19+ // Request twice at the same time
20+ // NOTE: These two requests will return a wrong view count, they'll both say it's 1
21+ request ( `${ url } /path` )
22+ request ( `${ url } /path` )
23+ // After the data is persisted (in the mocked case after 10ms) the path shows the right view count
24+ setTimeout ( async ( ) => {
25+ const body = JSON . parse ( await request ( `${ url } /path` ) )
26+ expect ( body . views ) . toEqual ( 3 )
27+ } , 10 )
28+ } )
Original file line number Diff line number Diff line change @@ -6,11 +6,8 @@ const service = require('../src')
66let url
77
88beforeEach ( async ( ) => {
9- url = await listen ( service )
10- } )
11-
12- afterEach ( async ( ) => {
139 mockDb . _reset ( )
10+ url = await listen ( service )
1411} )
1512
1613describe ( 'single' , ( ) => {
Original file line number Diff line number Diff line change @@ -17,7 +17,7 @@ const DB = () => {
1717 keys : ( ) => Object . keys ( data ) ,
1818 // Custom methods used in tests
1919 _reset : ( ) => { data = { } } ,
20- _setDelay : ( ms ) => { DELAY = ms }
20+ _setDelay : ( ms ) => { DELAY = ms || 1 }
2121 }
2222}
2323
You can’t perform that action at this time.
0 commit comments