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

fix: ensure writes are always atomic #97

Closed
wants to merge 11 commits into from
Closed

Conversation

ronag
Copy link
Contributor

@ronag ronag commented Aug 26, 2021

Fixes: #96

@ronag ronag force-pushed the atomic-write branch 2 times, most recently from 6a8f787 to 61c4bb8 Compare August 26, 2021 07:20
index.js Outdated Show resolved Hide resolved
index.js Outdated Show resolved Hide resolved
index.js Outdated Show resolved Hide resolved
index.js Outdated Show resolved Hide resolved
@mcollina
Copy link
Member

why did you close this?

@ronag ronag reopened this Aug 26, 2021
@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

missing tests

@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

There is one problem here. We can still write larger than MAX_WRITE if the source doesn't properly pause given the return value of write. But I suppose that's not a big problem? Otherwise the solution becomes more complicated and slower (_buf would need to be an array of strings).

@mcollina
Copy link
Member

We can still write larger than MAX_WRITE if the source doesn't properly pause given the return value of write

This is the case of pino.

@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

So this PR is not sufficient.

@ronag ronag closed this Aug 26, 2021
@ronag ronag reopened this Aug 26, 2021
@ronag ronag marked this pull request as draft August 26, 2021 10:43
@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

@mcollina PTAL, doesn't pass tests but I think this could potentially work.

@mcollina
Copy link
Member

Agreed, this is quite nice actually

@ronag ronag marked this pull request as ready for review August 26, 2021 12:26
@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

passes all tests except for retry in flushSync on EAGAIN. The whole flushSync I don't understand how it can work when there is a pending async write...

@mcollina
Copy link
Member

I'm getting a lot of failures while running your branch locally.

1..12
# failed 8 of 12 tests
# time=2439.583ms

@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

Should be better now. Sorry about that.

@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

the write enormously large buffers test seems to take a very long time to finish now...

@mcollina
Copy link
Member

I can see some slowdown but it seems acceptable to solve this problem:

This branch:

benchSonic*1000: 521.245ms
benchSonicSync*1000: 6.851s
benchSonic4k*1000: 466.171ms
benchSonicSync4k*1000: 336.917ms
benchCore*1000: 4.511s
benchConsole*1000: 9.480s

master:

benchSonic*1000: 498.087ms
benchSonicSync*1000: 6.710s
benchSonic4k*1000: 431.978ms
benchSonicSync4k*1000: 295.552ms
benchCore*1000: 4.516s
benchConsole*1000: 9.521s

We can see if there are a few areas were we could optimize.

@mcollina
Copy link
Member

The following fixes the broken test:

diff --git a/index.js b/index.js
index fc19cdf..a3118a6 100644
--- a/index.js
+++ b/index.js
@@ -145,8 +145,8 @@ function SonicBoom (opts) {
         this.emit('error', err)
       }
       return
-    }
-
+    }
+
     this._len -= n
     this._writingBuf = this._writingBuf.slice(n)

@@ -335,12 +335,14 @@ SonicBoom.prototype.flushSync = function () {
   }

   while (this._bufs.length) {
+    const buf = this._bufs.shift()
     try {
-      this._len -= fs.writeSync(this.fd, this._bufs.shift(), 'utf8')
+      this._len -= fs.writeSync(this.fd, buf, 'utf8')
     } catch (err) {
       if (err.code !== 'EAGAIN') {
         throw err
       }
+      this._bufs.unshift(buf)

       sleep(BUSY_WRITE_TIMEOUT)
     }

Essentially the flushSync() implementation did not reinsert the shifted buffer in.

@ronag
Copy link
Contributor Author

ronag commented Aug 26, 2021

Thanks! Fixed.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@ronag
Copy link
Contributor Author

ronag commented Aug 27, 2021

#102

@ronag ronag closed this Aug 27, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MAX_WRITE can cause messages to split
2 participants