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

feat: implements unlisten functionality #155

Merged
merged 4 commits into from
Mar 5, 2021

Conversation

stalniy
Copy link
Contributor

@stalniy stalniy commented Feb 24, 2021

Relates to #133

BREAKING CHANGE: listen function returns an object instead of an empty array. All properties are preserved.

Copy link
Owner

@porsager porsager left a comment

Choose a reason for hiding this comment

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

I think it'd be great if we could fix subsequent listen calls not receiving the result, in this PR too. Are you up for that? It effects the way unlisten is implemented, but it's odd if only the first listener is able to unlisten.

lib/index.js Outdated Show resolved Hide resolved
So, the client can unlisten any of its subscription
@stalniy
Copy link
Contributor Author

stalniy commented Feb 25, 2021

Also Fixes #154

Copy link
Contributor

@Minigugus Minigugus left a comment

Choose a reason for hiding this comment

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

Great work! And don't forget to update the types 😉

https://github.com/porsager/postgres/blob/master/types/index.d.ts#L340

(I can help with types if you want by the way)

lib/index.js Show resolved Hide resolved
@stalniy
Copy link
Contributor Author

stalniy commented Feb 26, 2021

updated types

@stalniy
Copy link
Contributor Author

stalniy commented Mar 1, 2021

@porsager do you have any feedback after updates?

@porsager
Copy link
Owner

porsager commented Mar 1, 2021

I'll take a look tonight.

Would you review the types @Minigugus ?

lib/index.js Outdated
if (channel in listeners) {
listeners[channel].push(fn)
return Promise.resolve(channel)
return Promise.resolve(listener.result)
Copy link
Owner

Choose a reason for hiding this comment

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

This will result in any listener receiving an unlisten function that only works for the initial listener.

Here's one of the test cases modified to test this.

ot('multiple listeners and unlisten one', async() => {
  const listener = postgres(options)
      , xs = []

  await listener.listen('test', x => xs.push('1', x))
  const s2 = await listener.listen('test', x => xs.push('2', x))
  await listener.notify('test', 'a')
  await delay(50)
  await s2.unlisten()
  await listener.notify('test', 'b')
  await delay(50)
  listener.end();

  return ['1a2a1b', xs.join('')]
})

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, right... unlisten is different for every fn

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@stalniy
Copy link
Contributor Author

stalniy commented Mar 1, 2021

I changed return type of sql.listen because it seems strange to copy an array with Object.assign but if you would like the return result to be an array, I will do this.

Update: that array is always empty, so very unlikely that anybody relied on it to be an array

@Minigugus
Copy link
Contributor

Minigugus commented Mar 1, 2021

that array is always empty, so very unlikely that anybody relied on it to be an array

Ok, it's not a bad idea since it hide implementation details and simplify the public API :)

It's also a breaking change, maybe you should also update the changelog 😉

Would you review the types @Minigugus ?

Types looks good :)

@stalniy
Copy link
Contributor Author

stalniy commented Mar 2, 2021

Ok, it's not a bad idea since it hide implementation details and simplify the public API :)

where can I find it?

@Minigugus
Copy link
Contributor

where can I find it?

Ok I thought there was a changelog file, my bad x)

Then there is nothing to, only @porsager is responsible for what is in the changelog on the release page.

@porsager
Copy link
Owner

porsager commented Mar 5, 2021

I think it's fine that the return type is simply { unsubscribe }.

With regards to the changelog, add it as part of the PR description and then I'll add it to releases.

@stalniy
Copy link
Contributor Author

stalniy commented Mar 5, 2021

I think it's fine that the return type is simply { unsubscribe }.

With regards to the changelog, add it as part of the PR description and then I'll add it to releases.

shall I change the return type?

@porsager
Copy link
Owner

porsager commented Mar 5, 2021

I don't think there's any use case for having the result included, so if you agree let's do it :)

@stalniy
Copy link
Contributor Author

stalniy commented Mar 5, 2021

@porsager looks like we can't leave unlisten only. there is a test that check listen reconnect and requires connection pid:

t('listen reconnects', async() => {
  const listener = postgres(options)
      , xs = []

  const { state: { pid } } = await listener.listen('test', x => xs.push(x))
  await sql.notify('test', 'a')
  await sql`select pg_terminate_backend(${ pid }::int)`
  await delay(50)
  await sql.notify('test', 'b')
  await delay(50)
  listener.end()

  return ['ab', xs.join('')]
})

@stalniy
Copy link
Contributor Author

stalniy commented Mar 5, 2021

I actually like that it returns pid because I planned to implement similar set of tests on my side :)

@porsager
Copy link
Owner

porsager commented Mar 5, 2021 via email

@porsager porsager merged commit 6ef71c8 into porsager:master Mar 5, 2021
@porsager
Copy link
Owner

porsager commented Mar 5, 2021

That was a little too soon though. The pid will change if the underlying socket reconnects. Let's tackle that in another PR

@stalniy
Copy link
Contributor Author

stalniy commented Mar 5, 2021

Hmm... I think a good way to handle this is to turn pid into a function/getter. So, we do not update this value for every subscription

@porsager
Copy link
Owner

porsager commented Mar 5, 2021

Yeah, sounds good.

@stalniy
Copy link
Contributor Author

stalniy commented Mar 9, 2021

@porsager how to test unequality or comparison? I'd like to add a test that checks unequality of initial pid and a pid which I get after terminating connection:

t('listen result has state getter', async() => {
  const listener = postgres(options)
      , xs = []

  const result = await listener.listen('test', x => xs.push(x))
  const initialPid = result.state.pid
  await sql.notify('test', 'a')
  await sql`select pg_terminate_backend(${ initialPid }::int)`
  await delay(50)
  listener.end()

  return [result.state.pid, initialPid] // <--- looks like there is no way to check unequality
})

Let's discuss this in #160

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.

3 participants