mirror of
https://github.com/openfaas/faas.git
synced 2025-06-22 23:03:24 +00:00
Vendor new queue-worker version
Introduces 0.4.6 of queue-worker - see upstream repo for changes. Signed-off-by: Alex Ellis (VMware) <alexellis2@gmail.com>
This commit is contained in:
18
gateway/vendor/github.com/nats-io/go-nats-streaming/.travis.yml
generated
vendored
18
gateway/vendor/github.com/nats-io/go-nats-streaming/.travis.yml
generated
vendored
@ -1,22 +1,26 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.6.4
|
||||
- 1.7.4
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
install:
|
||||
- go get -t ./...
|
||||
- go get github.com/nats-io/nats-streaming-server
|
||||
- go get github.com/mattn/goveralls
|
||||
- go get github.com/wadey/gocovmerge
|
||||
- go get honnef.co/go/staticcheck/cmd/staticcheck
|
||||
script:
|
||||
- go fmt ./...
|
||||
- go get -u honnef.co/go/tools/cmd/megacheck
|
||||
- go get -u github.com/client9/misspell/cmd/misspell
|
||||
before_script:
|
||||
- $(exit $(go fmt ./... | wc -l))
|
||||
- go vet ./...
|
||||
- misspell -error -locale US .
|
||||
- megacheck ./...
|
||||
script:
|
||||
- go test -i -race ./...
|
||||
- go test -v -race ./...
|
||||
- staticcheck ./...
|
||||
after_success:
|
||||
- if [ "$TRAVIS_GO_VERSION" \> "1.7." ]; then ./scripts/cov.sh TRAVIS; fi
|
||||
- if [[ "$TRAVIS_GO_VERSION" == 1.9.* ]]; then ./scripts/cov.sh TRAVIS; fi
|
||||
env:
|
||||
global:
|
||||
secure: OoCemKSHHH/SkkamHLWd0qh9qgQDx4/3fGuykYuzW/gjUhLlL0ThyUXOr3HOandoh3wTU8Ntj184WU6Sjh1oXzdDAYcI/ryNQXSmJ/DyGC6ffoj4Je/Rwj3sbwpaFTl1imawL8Lv6+5Dkb2JSbbbqapjbO3BhrrNfqLuQulqrLJKVaOyS5nOByiGFYsgjf/ac7Qrr9AnHhlkWRXoR+q8GlGG7qcKtLlmG5OqxifqfgQ+pcVtyeleT6zGPI0LUyr9gWHRZtMK9nYfxXuQK2d7V+SW4NBW1jdDKBHZbeJRxZ8N8rU8Nk3ka54YHXC2PeD8EloiAr5HkALuHbIdzyy40Y3rJyHfxyY6EYBcZEy+ZCRoqkVJ4NN4R46YE588BpYhT48YHK+lptM7YxrPtf08X+Cugc206X0hk/YFqqsaaNIwMfiTPbapuHxa8S4kgT2vDn3OTI53ZTrDiLVY3ZDp+EdUO1hiYFR6cpu5el/EQN5G0iW6sI69gOv26UmGI369D3fezbYPFPHHDao8xq7s8HdYUZleDNL0oCWK1MgL2g/Irbt5Kr6JjT/tpQOiiagqeR5dlV9mAiOZFr88gg7aqwOuSqmlULWVB4qYncQ6IBoednIHtrLW6H+2RfrZU01cI6tGSrXD+VoFnQ7aZwLxLc71VyN5khYPk0gGvyQhZxk=
|
||||
|
4
gateway/vendor/github.com/nats-io/go-nats-streaming/CODE-OF-CONDUCT.md
generated
vendored
Normal file
4
gateway/vendor/github.com/nats-io/go-nats-streaming/CODE-OF-CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
## Community Code of Conduct
|
||||
|
||||
NATS follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
213
gateway/vendor/github.com/nats-io/go-nats-streaming/LICENSE
generated
vendored
213
gateway/vendor/github.com/nats-io/go-nats-streaming/LICENSE
generated
vendored
@ -1,20 +1,201 @@
|
||||
The MIT License (MIT)
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
Copyright (c) 2016 Apcera Inc.
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
1. Definitions.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
9
gateway/vendor/github.com/nats-io/go-nats-streaming/OWNERS
generated
vendored
Normal file
9
gateway/vendor/github.com/nats-io/go-nats-streaming/OWNERS
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
reviewers:
|
||||
- aricart
|
||||
- ColinSullivan1
|
||||
- derekcollison
|
||||
- kozlovic
|
||||
- wallyqs
|
||||
approvers:
|
||||
- derekcollison
|
||||
- kozlovic
|
96
gateway/vendor/github.com/nats-io/go-nats-streaming/README.md
generated
vendored
96
gateway/vendor/github.com/nats-io/go-nats-streaming/README.md
generated
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
NATS Streaming is an extremely performant, lightweight reliable streaming platform powered by [NATS](https://nats.io).
|
||||
|
||||
[](http://opensource.org/licenses/MIT)
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](http://travis-ci.org/nats-io/go-nats-streaming)
|
||||
[](https://coveralls.io/r/nats-io/go-nats-streaming?branch=master)
|
||||
|
||||
@ -17,9 +17,6 @@ NATS Streaming provides the following high-level feature set:
|
||||
|
||||
- Please raise questions/issues via the [Issue Tracker](https://github.com/nats-io/go-nats-streaming/issues).
|
||||
|
||||
## Known Issues
|
||||
- Time- and sequence-based subscriptions are exact. Requesting a time or seqno before the earliest stored message for a subject will result in an error (in SubscriptionRequest.Error)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
@ -59,29 +56,29 @@ The options are described with examples below:
|
||||
// Subscribe starting with most recently published value
|
||||
sub, err := sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||
}, StartWithLastReceived())
|
||||
}, stan.StartWithLastReceived())
|
||||
|
||||
// Receive all stored values in order
|
||||
sub, err := sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||
}, DeliverAllAvailable())
|
||||
}, stan.DeliverAllAvailable())
|
||||
|
||||
// Receive messages starting at a specific sequence number
|
||||
sub, err := sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||
}, StartAtSequence(22))
|
||||
}, stan.StartAtSequence(22))
|
||||
|
||||
// Subscribe starting at a specific time
|
||||
var startTime time.Time
|
||||
...
|
||||
sub, err := sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||
}, StartAtTime(startTime))
|
||||
}, stan.StartAtTime(startTime))
|
||||
|
||||
// Subscribe starting a specific amount of time in the past (e.g. 30 seconds ago)
|
||||
sub, err := sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
fmt.Printf("Received a message: %s\n", string(m.Data))
|
||||
}, StartAtTimeDelta(time.ParseDuration("30s")))
|
||||
}, stan.StartAtTimeDelta(time.ParseDuration("30s")))
|
||||
```
|
||||
|
||||
### Durable Subscriptions
|
||||
@ -184,7 +181,7 @@ that is, the start position will take effect and delivery will start from there.
|
||||
|
||||
### Durable Queue Groups
|
||||
|
||||
As described above, for non durable queue subsribers, when the last member leaves the group,
|
||||
As described above, for non durable queue subscribers, when the last member leaves the group,
|
||||
that group is removed. A durable queue group allows you to have all members leave but still
|
||||
maintain state. When a member re-joins, it starts at the last position in that group.
|
||||
|
||||
@ -220,7 +217,7 @@ The rules for non-durable queue subscribers apply to durable subscribers.
|
||||
|
||||
As for non-durable queue subscribers, if a member's connection is closed, or if
|
||||
`Unsubscribe` its called, the member leaves the group. Any unacknowledged message
|
||||
is transfered to remaining members. See *Closing the Group* for important difference
|
||||
is transferred to remaining members. See *Closing the Group* for important difference
|
||||
with non-durable queue subscribers.
|
||||
|
||||
#### Closing the Group
|
||||
@ -242,6 +239,58 @@ NATS Streaming subscriptions **do not** support wildcards.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Connection Status
|
||||
|
||||
The fact that the NATS Streaming server and clients are not directly connected poses a challenge when it comes to know if a client is still valid.
|
||||
When a client disconnects, the streaming server is not notified, hence the importance of calling `Close()`. The server sends heartbeats
|
||||
to the client's private inbox and if it misses a certain number of responses, it will consider the client's connection lost and remove it
|
||||
from its state.
|
||||
|
||||
Before version `0.4.0`, the client library was not sending PINGs to the streaming server to detect connection failure. This was problematic
|
||||
especially if an application was never sending data (had only subscriptions for instance). Picture the case where a client connects to a
|
||||
NATS Server which has a route to a NATS Streaming server (either connecting to a standalone NATS Server or the server it embeds). If the
|
||||
connection between the streaming server and the client's NATS Server is broken, the client's NATS connection would still be ok, yet, no
|
||||
communication with the streaming server is possible. This is why relying on `Conn.NatsConn()` to check the status is not helpful.
|
||||
|
||||
Starting version `0.4.0` of this library and server `0.10.0`, the client library will now send PINGs at regular intervals (default is 5 seconds)
|
||||
and will close the streaming connection after a certain number of PINGs have been sent without any response (default is 3). When that
|
||||
happens, a callback - if one is registered - will be invoked to notify the user that the connection is permanently lost, and the reason
|
||||
for the failure.
|
||||
|
||||
Here is how you would specify your own PING values and the callback:
|
||||
|
||||
```go
|
||||
|
||||
// Send PINGs every 10 seconds, and fail after 5 PINGs without any response.
|
||||
sc, err := stan.Connect(clusterName, clientName,
|
||||
stan.Pings(10, 5),
|
||||
stan.SetConnectionLostHandler(func(_ stan.Conn, reason error) {
|
||||
log.Fatalf("Connection lost, reason: %v", reason)
|
||||
}))
|
||||
```
|
||||
|
||||
Note that the only way to be notified is to set the callback. If the callback is not set, PINGs are still sent and the connection
|
||||
will be closed if needed, but the application won't know if it has only subscriptions.
|
||||
|
||||
When the connection is lost, your application would have to re-create it and all subscriptions if any.
|
||||
|
||||
When no NATS connection is provided to the `Connect()` call, the library creates its own NATS connection and will now
|
||||
set the reconnect attempts to "infinite", which was not the case before. It should therefore be possible for the library to
|
||||
always reconnect, but this does not mean that the streaming connection will not be closed, even if you set a very high
|
||||
threshold for the PINGs max out value. Keep in mind that while the client is disconnected, the server is sending heartbeats to
|
||||
the clients too, and when not getting any response, it will remove that client from its state. When the communication is restored,
|
||||
the PINGs sent to the server will allow to detect this condition and report to the client that the connection is now closed.
|
||||
|
||||
Also, while a client is "disconnected" from the server, another application with connectivity to the streaming server may
|
||||
connect and uses the same client ID. The server, when detecting the duplicate client ID, will try to contact the first client
|
||||
to know if it should reject the connect request of the second client. Since the communication between the server and the
|
||||
first client is broken, the server will not get a response and therefore will replace the first client with the second one.
|
||||
|
||||
Prior to client `0.4.0` and server `0.10.0`, if the communication between the first client and server were to be restored,
|
||||
and the application would send messages, the server would accept those because the published messages client ID would be
|
||||
valid, although the client is not. With client at `0.4.0+` and server `0.10.0+`, additional information is sent with each
|
||||
message to allow the server to reject messages from a client that has been replaced by another client.
|
||||
|
||||
### Asynchronous Publishing
|
||||
|
||||
The basic publish API (`Publish(subject, payload)`) is synchronous; it does not return control to the caller until the NATS Streaming server has acknowledged receipt of the message. To accomplish this, a [NUID](https://github.com/nats-io/nuid) is generated for the message on creation, and the client library waits for a publish acknowledgement from the server with a matching NUID before it returns control to the caller, possibly with an error indicating that the operation was not successful due to some server problem or authorization error.
|
||||
@ -301,7 +350,7 @@ ah := func(nuid string, err error) {
|
||||
}
|
||||
|
||||
for i := 1; i < 1000; i++ {
|
||||
// If the server is unable to keep up with the publisher, the number of oustanding acks will eventually
|
||||
// If the server is unable to keep up with the publisher, the number of outstanding acks will eventually
|
||||
// reach the max and this call will block
|
||||
guid, _ := sc.PublishAsync("foo", []byte("Hello World"), ah)
|
||||
}
|
||||
@ -327,24 +376,5 @@ sc.Subscribe("foo", func(m *stan.Msg) {
|
||||
|
||||
## License
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2016 Apcera Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
Unless otherwise noted, the NATS source files are distributed
|
||||
under the Apache Version 2.0 license found in the LICENSE file.
|
15
gateway/vendor/github.com/nats-io/go-nats-streaming/TODO.md
generated
vendored
15
gateway/vendor/github.com/nats-io/go-nats-streaming/TODO.md
generated
vendored
@ -1,15 +0,0 @@
|
||||
|
||||
- [ ] Retry limits?
|
||||
- [ ] Server Store Limits (time, msgs, byte)
|
||||
- [X] Change time to deltas
|
||||
- [X] Server heartbeat, release dead clients.
|
||||
- [X] Require clientID for published messages, error if not registered.
|
||||
- [X] Check for need of ackMap (out of order re-delivery to queue subscribers).
|
||||
- [X] Redelivered Flag for Msg.
|
||||
- [X] Queue Subscribers
|
||||
- [X] Durable Subscribers (survive reconnect, etc)
|
||||
- [X] Start Positions on Subscribers
|
||||
- [X] Ack for delivered just Reply? No need on ConnectedResponse?
|
||||
- [X] PublishWithReply, or option.
|
||||
- [X] Data Races in Server.
|
||||
- [X] Manual Ack?
|
12
gateway/vendor/github.com/nats-io/go-nats-streaming/benchmark_test.go
generated
vendored
12
gateway/vendor/github.com/nats-io/go-nats-streaming/benchmark_test.go
generated
vendored
@ -1,3 +1,15 @@
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package stan
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,4 +1,15 @@
|
||||
// Copyright 2015 Apcera Inc. All rights reserved.
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
@ -29,12 +40,16 @@ const (
|
||||
)
|
||||
|
||||
func usage() {
|
||||
log.Fatalf("Usage: nats-bench [-s server (%s)] [--tls] [-id CLIENT_ID] [-np NUM_PUBLISHERS] [-ns NUM_SUBSCRIBERS] [-n NUM_MSGS] [-ms MESSAGE_SIZE] [-csv csvfile] [-mpa MAX_NUMBER_OF_PUBLISHED_ACKS_INFLIGHT] [-io] [-a] <subject>\n", nats.DefaultURL)
|
||||
log.Fatalf("Usage: stan-bench [-s server (%s)] [--tls] [-id CLIENT_ID] [-np NUM_PUBLISHERS] [-ns NUM_SUBSCRIBERS] [-n NUM_MSGS] [-ms MESSAGE_SIZE] [-csv csvfile] [-mpa MAX_NUMBER_OF_PUBLISHED_ACKS_INFLIGHT] [-io] [-a] <subject>\n", nats.DefaultURL)
|
||||
}
|
||||
|
||||
var benchmark *bench.Benchmark
|
||||
|
||||
func main() {
|
||||
var clusterID string
|
||||
flag.StringVar(&clusterID, "c", "test-cluster", "The NATS Streaming cluster ID")
|
||||
flag.StringVar(&clusterID, "cluster", "test-cluster", "The NATS Streaming cluster ID")
|
||||
|
||||
var urls = flag.String("s", nats.DefaultURL, "The NATS server URLs (separated by comma")
|
||||
var tls = flag.Bool("tls", false, "Use TLS secure sonnection")
|
||||
var numPubs = flag.Int("np", DefaultNumPubs, "Number of concurrent publishers")
|
||||
@ -57,7 +72,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Setup the option block
|
||||
opts := nats.DefaultOptions
|
||||
opts := nats.GetDefaultOptions()
|
||||
opts.Servers = strings.Split(*urls, ",")
|
||||
for i, s := range opts.Servers {
|
||||
opts.Servers[i] = strings.Trim(s, " ")
|
||||
@ -76,7 +91,7 @@ func main() {
|
||||
startwg.Add(*numSubs)
|
||||
for i := 0; i < *numSubs; i++ {
|
||||
subID := fmt.Sprintf("%s-sub-%d", *clientID, i)
|
||||
go runSubscriber(&startwg, &donewg, opts, *numMsgs, *messageSize, *ignoreOld, subID)
|
||||
go runSubscriber(&startwg, &donewg, opts, clusterID, *numMsgs, *messageSize, *ignoreOld, subID)
|
||||
}
|
||||
startwg.Wait()
|
||||
|
||||
@ -85,7 +100,7 @@ func main() {
|
||||
pubCounts := bench.MsgsPerClient(*numMsgs, *numPubs)
|
||||
for i := 0; i < *numPubs; i++ {
|
||||
pubID := fmt.Sprintf("%s-pub-%d", *clientID, i)
|
||||
go runPublisher(&startwg, &donewg, opts, pubCounts[i], *messageSize, *async, pubID, *maxPubAcks)
|
||||
go runPublisher(&startwg, &donewg, opts, clusterID, pubCounts[i], *messageSize, *async, pubID, *maxPubAcks)
|
||||
}
|
||||
|
||||
log.Printf("Starting benchmark [msgs=%d, msgsize=%d, pubs=%d, subs=%d]\n", *numMsgs, *messageSize, *numPubs, *numSubs)
|
||||
@ -103,12 +118,15 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func runPublisher(startwg, donewg *sync.WaitGroup, opts nats.Options, numMsgs int, msgSize int, async bool, pubID string, maxPubAcksInflight int) {
|
||||
func runPublisher(startwg, donewg *sync.WaitGroup, opts nats.Options, clusterID string, numMsgs int, msgSize int, async bool, pubID string, maxPubAcksInflight int) {
|
||||
nc, err := opts.Connect()
|
||||
if err != nil {
|
||||
log.Fatalf("Publisher %s can't connect: %v\n", pubID, err)
|
||||
}
|
||||
snc, err := stan.Connect("test-cluster", pubID, stan.MaxPubAcksInflight(maxPubAcksInflight), stan.NatsConn(nc))
|
||||
snc, err := stan.Connect(clusterID, pubID, stan.MaxPubAcksInflight(maxPubAcksInflight), stan.NatsConn(nc),
|
||||
stan.SetConnectionLostHandler(func(_ stan.Conn, reason error) {
|
||||
log.Fatalf("Connection lost, reason: %v", reason)
|
||||
}))
|
||||
if err != nil {
|
||||
log.Fatalf("Publisher %s can't connect: %v\n", pubID, err)
|
||||
}
|
||||
@ -128,6 +146,9 @@ func runPublisher(startwg, donewg *sync.WaitGroup, opts nats.Options, numMsgs in
|
||||
if async {
|
||||
ch := make(chan bool)
|
||||
acb := func(lguid string, err error) {
|
||||
if err != nil {
|
||||
log.Fatalf("Publisher %q got following error: %v", pubID, err)
|
||||
}
|
||||
published++
|
||||
if published >= numMsgs {
|
||||
ch <- true
|
||||
@ -156,26 +177,31 @@ func runPublisher(startwg, donewg *sync.WaitGroup, opts nats.Options, numMsgs in
|
||||
donewg.Done()
|
||||
}
|
||||
|
||||
func runSubscriber(startwg, donewg *sync.WaitGroup, opts nats.Options, numMsgs int, msgSize int, ignoreOld bool, subID string) {
|
||||
func runSubscriber(startwg, donewg *sync.WaitGroup, opts nats.Options, clusterID string, numMsgs int, msgSize int, ignoreOld bool, subID string) {
|
||||
nc, err := opts.Connect()
|
||||
if err != nil {
|
||||
log.Fatalf("Subscriber %s can't connect: %v\n", subID, err)
|
||||
}
|
||||
snc, err := stan.Connect("test-cluster", subID, stan.NatsConn(nc))
|
||||
snc, err := stan.Connect(clusterID, subID, stan.NatsConn(nc),
|
||||
stan.SetConnectionLostHandler(func(_ stan.Conn, reason error) {
|
||||
log.Fatalf("Connection lost, reason: %v", reason)
|
||||
}))
|
||||
if err != nil {
|
||||
log.Fatalf("Subscriber %s can't connect: %v\n", subID, err)
|
||||
}
|
||||
|
||||
args := flag.Args()
|
||||
subj := args[0]
|
||||
ch := make(chan bool)
|
||||
start := time.Now()
|
||||
ch := make(chan time.Time, 2)
|
||||
|
||||
received := 0
|
||||
mcb := func(msg *stan.Msg) {
|
||||
received++
|
||||
if received == 1 {
|
||||
ch <- time.Now()
|
||||
}
|
||||
if received >= numMsgs {
|
||||
ch <- true
|
||||
ch <- time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,8 +212,9 @@ func runSubscriber(startwg, donewg *sync.WaitGroup, opts nats.Options, numMsgs i
|
||||
}
|
||||
startwg.Done()
|
||||
|
||||
<-ch
|
||||
benchmark.AddSubSample(bench.NewSample(numMsgs, msgSize, start, time.Now(), snc.NatsConn()))
|
||||
start := <-ch
|
||||
end := <-ch
|
||||
benchmark.AddSubSample(bench.NewSample(numMsgs, msgSize, start, end, snc.NatsConn()))
|
||||
snc.Close()
|
||||
nc.Close()
|
||||
donewg.Done()
|
@ -1,5 +1,15 @@
|
||||
// Copyright 2012-2016 Apcera Inc. All rights reserved.
|
||||
// +build ignore
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
@ -79,7 +89,7 @@ func main() {
|
||||
ch <- true
|
||||
}
|
||||
|
||||
if async != true {
|
||||
if !async {
|
||||
err = sc.Publish(subj, msg)
|
||||
if err != nil {
|
||||
log.Fatalf("Error during publish: %v\n", err)
|
@ -1,5 +1,15 @@
|
||||
// Copyright 2012-2016 Apcera Inc. All rights reserved.
|
||||
// +build ignore
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
@ -89,7 +99,10 @@ func main() {
|
||||
usage()
|
||||
}
|
||||
|
||||
sc, err := stan.Connect(clusterID, clientID, stan.NatsURL(URL))
|
||||
sc, err := stan.Connect(clusterID, clientID, stan.NatsURL(URL),
|
||||
stan.SetConnectionLostHandler(func(_ stan.Conn, reason error) {
|
||||
log.Fatalf("Connection lost, reason: %v", reason)
|
||||
}))
|
||||
if err != nil {
|
||||
log.Fatalf("Can't connect: %v.\nMake sure a NATS Streaming Server is running at: %s", err, URL)
|
||||
}
|
||||
@ -106,9 +119,9 @@ func main() {
|
||||
|
||||
if startSeq != 0 {
|
||||
startOpt = stan.StartAtSequence(startSeq)
|
||||
} else if deliverLast == true {
|
||||
} else if deliverLast {
|
||||
startOpt = stan.StartWithLastReceived()
|
||||
} else if deliverAll == true {
|
||||
} else if deliverAll {
|
||||
log.Print("subscribing with DeliverAllAvailable")
|
||||
startOpt = stan.DeliverAllAvailable()
|
||||
} else if startDelta != "" {
|
||||
@ -138,7 +151,7 @@ func main() {
|
||||
cleanupDone := make(chan bool)
|
||||
signal.Notify(signalChan, os.Interrupt)
|
||||
go func() {
|
||||
for _ = range signalChan {
|
||||
for range signalChan {
|
||||
fmt.Printf("\nReceived an interrupt, unsubscribing and closing connection...\n\n")
|
||||
// Do not unsubscribe a durable on exit, except if asked to.
|
||||
if durable == "" || unsubscribe {
|
1371
gateway/vendor/github.com/nats-io/go-nats-streaming/pb/protocol.pb.go
generated
vendored
1371
gateway/vendor/github.com/nats-io/go-nats-streaming/pb/protocol.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
32
gateway/vendor/github.com/nats-io/go-nats-streaming/pb/protocol.proto
generated
vendored
32
gateway/vendor/github.com/nats-io/go-nats-streaming/pb/protocol.proto
generated
vendored
@ -1,4 +1,15 @@
|
||||
// Copyright 2016 Apcera Inc. All rights reserved.
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Uses https://github.com/gogo/protobuf
|
||||
// compiled via `protoc -I=. -I=$GOPATH/src --gogofaster_out=. protocol.proto`
|
||||
@ -20,6 +31,7 @@ message PubMsg {
|
||||
string subject = 3; // subject
|
||||
string reply = 4; // optional reply
|
||||
bytes data = 5; // payload
|
||||
bytes connID = 6; // Connection ID. For servers that know about this field, clientID can be omitted
|
||||
|
||||
bytes sha256 = 10; // optional sha256 of data
|
||||
}
|
||||
@ -53,6 +65,10 @@ message Ack {
|
||||
message ConnectRequest {
|
||||
string clientID = 1; // Client name/identifier.
|
||||
string heartbeatInbox = 2; // Inbox for server initiated heartbeats.
|
||||
int32 protocol = 3; // Protocol the client is at.
|
||||
bytes connID = 4; // Connection ID, a way to uniquely identify a connection (no connection should ever have the same)
|
||||
int32 pingInterval = 5; // Interval at which client wishes to send PINGs (expressed in seconds).
|
||||
int32 pingMaxOut = 6; // Maximum number of PINGs without a response after which the connection can be considered lost.
|
||||
}
|
||||
|
||||
// Response to a client connect
|
||||
@ -63,10 +79,24 @@ message ConnectResponse {
|
||||
string closeRequests = 4; // Subject for closing the stan connection
|
||||
string error = 5; // err string, empty/omitted if no error
|
||||
string subCloseRequests = 6; // Subject to use for subscription close requests
|
||||
string pingRequests = 7; // Subject to use for PING requests
|
||||
int32 pingInterval = 8; // Interval at which client should send PINGs (expressed in seconds).
|
||||
int32 pingMaxOut = 9; // Maximum number of PINGs without a response after which the connection can be considered lost
|
||||
int32 protocol = 10; // Protocol version the server is at
|
||||
|
||||
string publicKey = 100; // Possibly used to sign acks, etc.
|
||||
}
|
||||
|
||||
// PING from client to server
|
||||
message Ping {
|
||||
bytes connID = 1; // Connection ID
|
||||
}
|
||||
|
||||
// PING response from the server
|
||||
message PingResponse {
|
||||
string error = 1; // Error string, empty/omitted if no error
|
||||
}
|
||||
|
||||
// Enum for start position type.
|
||||
enum StartPosition {
|
||||
NewOnly = 0;
|
||||
|
365
gateway/vendor/github.com/nats-io/go-nats-streaming/stan.go
generated
vendored
365
gateway/vendor/github.com/nats-io/go-nats-streaming/stan.go
generated
vendored
@ -1,4 +1,15 @@
|
||||
// Copyright 2016 Apcera Inc. All rights reserved.
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package stan is a Go client for the NATS Streaming messaging system (https://nats.io).
|
||||
package stan
|
||||
@ -16,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
// Version is the NATS Streaming Go Client version
|
||||
const Version = "0.3.4"
|
||||
const Version = "0.4.0"
|
||||
|
||||
const (
|
||||
// DefaultNatsURL is the default URL the client connects to
|
||||
@ -30,6 +41,10 @@ const (
|
||||
// DefaultMaxPubAcksInflight is the default maximum number of published messages
|
||||
// without outstanding ACKs from the server
|
||||
DefaultMaxPubAcksInflight = 16384
|
||||
// DefaultPingInterval is the default interval (in seconds) at which a connection sends a PING to the server
|
||||
DefaultPingInterval = 5
|
||||
// DefaultPingMaxOut is the number of PINGs without a response before the connection is considered lost.
|
||||
DefaultPingMaxOut = 3
|
||||
)
|
||||
|
||||
// Conn represents a connection to the NATS Streaming subsystem. It can Publish and
|
||||
@ -54,6 +69,13 @@ type Conn interface {
|
||||
NatsConn() *nats.Conn
|
||||
}
|
||||
|
||||
const (
|
||||
// Client send connID in ConnectRequest and PubMsg, and server
|
||||
// listens and responds to client PINGs. The validity of the
|
||||
// connection (based on connID) is checked on incoming PINGs.
|
||||
protocolOne = int32(1)
|
||||
)
|
||||
|
||||
// Errors
|
||||
var (
|
||||
ErrConnectReqTimeout = errors.New("stan: connect request timeout")
|
||||
@ -68,13 +90,20 @@ var (
|
||||
ErrManualAck = errors.New("stan: cannot manually ack in auto-ack mode")
|
||||
ErrNilMsg = errors.New("stan: nil message")
|
||||
ErrNoServerSupport = errors.New("stan: not supported by server")
|
||||
ErrMaxPings = errors.New("stan: connection lost due to PING failure")
|
||||
)
|
||||
|
||||
var testAllowMillisecInPings = false
|
||||
|
||||
// AckHandler is used for Async Publishing to provide status of the ack.
|
||||
// The func will be passed teh GUID and any error state. No error means the
|
||||
// The func will be passed the GUID and any error state. No error means the
|
||||
// message was successfully received by NATS Streaming.
|
||||
type AckHandler func(string, error)
|
||||
|
||||
// ConnectionLostHandler is used to be notified if the Streaming connection
|
||||
// is closed due to unexpected errors.
|
||||
type ConnectionLostHandler func(Conn, error)
|
||||
|
||||
// Options can be used to a create a customized connection.
|
||||
type Options struct {
|
||||
NatsURL string
|
||||
@ -83,6 +112,9 @@ type Options struct {
|
||||
AckTimeout time.Duration
|
||||
DiscoverPrefix string
|
||||
MaxPubAcksInflight int
|
||||
PingIterval int // In seconds
|
||||
PingMaxOut int
|
||||
ConnectionLostCB ConnectionLostHandler
|
||||
}
|
||||
|
||||
// DefaultOptions are the NATS Streaming client's default options
|
||||
@ -92,6 +124,8 @@ var DefaultOptions = Options{
|
||||
AckTimeout: DefaultAckWait,
|
||||
DiscoverPrefix: DefaultDiscoverPrefix,
|
||||
MaxPubAcksInflight: DefaultMaxPubAcksInflight,
|
||||
PingIterval: DefaultPingInterval,
|
||||
PingMaxOut: DefaultPingMaxOut,
|
||||
}
|
||||
|
||||
// Option is a function on the options for a connection.
|
||||
@ -140,11 +174,45 @@ func NatsConn(nc *nats.Conn) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// Pings is an Option to set the ping interval and max out values.
|
||||
// The interval needs to be at least 1 and represents the number
|
||||
// of seconds.
|
||||
// The maxOut needs to be at least 2, since the count of sent PINGs
|
||||
// increase whenever a PING is sent and reset to 0 when a response
|
||||
// is received. Setting to 1 would cause the library to close the
|
||||
// connection right away.
|
||||
func Pings(interval, maxOut int) Option {
|
||||
return func(o *Options) error {
|
||||
// For tests, we may pass negative value that will be interpreted
|
||||
// by the library as milliseconds. If this test boolean is set,
|
||||
// do not check values.
|
||||
if !testAllowMillisecInPings {
|
||||
if interval < 1 || maxOut <= 2 {
|
||||
return fmt.Errorf("Invalid ping values: interval=%v (min>0) maxOut=%v (min=2)", interval, maxOut)
|
||||
}
|
||||
}
|
||||
o.PingIterval = interval
|
||||
o.PingMaxOut = maxOut
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetConnectionLostHandler is an Option to set the connection lost handler.
|
||||
// This callback will be invoked should the client permanently lose
|
||||
// contact with the server (or another client replaces it while being
|
||||
// disconnected). The callback will not be invoked on normal Conn.Close().
|
||||
func SetConnectionLostHandler(handler ConnectionLostHandler) Option {
|
||||
return func(o *Options) error {
|
||||
o.ConnectionLostCB = handler
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// A conn represents a bare connection to a stan cluster.
|
||||
type conn struct {
|
||||
sync.RWMutex
|
||||
clientID string
|
||||
serverID string
|
||||
connID []byte // This is a NUID that uniquely identify connections.
|
||||
pubPrefix string // Publish prefix set by stan, append our subject.
|
||||
subRequests string // Subject to send subscription requests.
|
||||
unsubRequests string // Subject to send unsubscribe requests.
|
||||
@ -158,7 +226,19 @@ type conn struct {
|
||||
pubAckChan chan (struct{})
|
||||
opts Options
|
||||
nc *nats.Conn
|
||||
ncOwned bool // NATS Streaming created the connection, so needs to close it.
|
||||
ncOwned bool // NATS Streaming created the connection, so needs to close it.
|
||||
pubNUID *nuid.NUID // NUID generator for published messages.
|
||||
connLostCB ConnectionLostHandler
|
||||
|
||||
pingMu sync.Mutex
|
||||
pingSub *nats.Subscription
|
||||
pingTimer *time.Timer
|
||||
pingBytes []byte
|
||||
pingRequests string
|
||||
pingInbox string
|
||||
pingInterval time.Duration
|
||||
pingMaxOut int
|
||||
pingOut int
|
||||
}
|
||||
|
||||
// Closure for ack contexts.
|
||||
@ -169,9 +249,10 @@ type ack struct {
|
||||
}
|
||||
|
||||
// Connect will form a connection to the NATS Streaming subsystem.
|
||||
// Note that clientID can contain only alphanumeric and `-` or `_` characters.
|
||||
func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
||||
// Process Options
|
||||
c := conn{clientID: clientID, opts: DefaultOptions}
|
||||
c := conn{clientID: clientID, opts: DefaultOptions, connID: []byte(nuid.Next()), pubNUID: nuid.New()}
|
||||
for _, opt := range options {
|
||||
if err := opt(&c.opts); err != nil {
|
||||
return nil, err
|
||||
@ -181,7 +262,15 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
||||
c.nc = c.opts.NatsConn
|
||||
// Create a NATS connection if it doesn't exist.
|
||||
if c.nc == nil {
|
||||
nc, err := nats.Connect(c.opts.NatsURL)
|
||||
// We will set the max reconnect attempts to -1 (infinite)
|
||||
// and the reconnect buffer to -1 to prevent any buffering
|
||||
// (which may cause a published message to be flushed on
|
||||
// reconnect while the API may have returned an error due
|
||||
// to PubAck timeout.
|
||||
nc, err := nats.Connect(c.opts.NatsURL,
|
||||
nats.Name(clientID),
|
||||
nats.MaxReconnects(-1),
|
||||
nats.ReconnectBufSize(-1))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -200,9 +289,25 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Prepare a subscription on ping responses, even if we are not
|
||||
// going to need it, so that if that fails, it fails before initiating
|
||||
// a connection.
|
||||
pingSub, err := c.nc.Subscribe(nats.NewInbox(), c.processPingResponse)
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Send Request to discover the cluster
|
||||
discoverSubject := c.opts.DiscoverPrefix + "." + stanClusterID
|
||||
req := &pb.ConnectRequest{ClientID: clientID, HeartbeatInbox: hbInbox}
|
||||
req := &pb.ConnectRequest{
|
||||
ClientID: clientID,
|
||||
HeartbeatInbox: hbInbox,
|
||||
ConnID: c.connID,
|
||||
Protocol: protocolOne,
|
||||
PingInterval: int32(c.opts.PingIterval),
|
||||
PingMaxOut: int32(c.opts.PingMaxOut),
|
||||
}
|
||||
b, _ := req.Marshal()
|
||||
reply, err := c.nc.Request(discoverSubject, b, c.opts.ConnectTimeout)
|
||||
if err != nil {
|
||||
@ -245,18 +350,172 @@ func Connect(stanClusterID, clientID string, options ...Option) (Conn, error) {
|
||||
|
||||
c.pubAckChan = make(chan struct{}, c.opts.MaxPubAcksInflight)
|
||||
|
||||
// Capture the connection error cb
|
||||
c.connLostCB = c.opts.ConnectionLostCB
|
||||
|
||||
unsubPingSub := true
|
||||
// Do this with servers which are at least at protcolOne.
|
||||
if cr.Protocol >= protocolOne {
|
||||
// Note that in the future server may override client ping
|
||||
// interval value sent in ConnectRequest, so use the
|
||||
// value in ConnectResponse to decide if we send PINGs
|
||||
// and at what interval.
|
||||
// In tests, the interval could be negative to indicate
|
||||
// milliseconds.
|
||||
if cr.PingInterval != 0 {
|
||||
unsubPingSub = false
|
||||
|
||||
// These will be immutable.
|
||||
c.pingRequests = cr.PingRequests
|
||||
c.pingInbox = pingSub.Subject
|
||||
// In test, it is possible that we get a negative value
|
||||
// to represent milliseconds.
|
||||
if testAllowMillisecInPings && cr.PingInterval < 0 {
|
||||
c.pingInterval = time.Duration(cr.PingInterval*-1) * time.Millisecond
|
||||
} else {
|
||||
// PingInterval is otherwise assumed to be in seconds.
|
||||
c.pingInterval = time.Duration(cr.PingInterval) * time.Second
|
||||
}
|
||||
c.pingMaxOut = int(cr.PingMaxOut)
|
||||
c.pingBytes, _ = (&pb.Ping{ConnID: c.connID}).Marshal()
|
||||
c.pingSub = pingSub
|
||||
// Set the timer now that we are set. Use lock to create
|
||||
// synchronization point.
|
||||
c.pingMu.Lock()
|
||||
c.pingTimer = time.AfterFunc(c.pingInterval, c.pingServer)
|
||||
c.pingMu.Unlock()
|
||||
}
|
||||
}
|
||||
if unsubPingSub {
|
||||
pingSub.Unsubscribe()
|
||||
}
|
||||
|
||||
// Attach a finalizer
|
||||
runtime.SetFinalizer(&c, func(sc *conn) { sc.Close() })
|
||||
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Sends a PING (containing the connection's ID) to the server at intervals
|
||||
// specified by PingInterval option when connection is created.
|
||||
// Everytime a PING is sent, the number of outstanding PINGs is increased.
|
||||
// If the total number is > than the PingMaxOut option, then the connection
|
||||
// is closed, and connection error callback invoked if one was specified.
|
||||
func (sc *conn) pingServer() {
|
||||
sc.pingMu.Lock()
|
||||
// In case the timer fired while we were stopping it.
|
||||
if sc.pingTimer == nil {
|
||||
sc.pingMu.Unlock()
|
||||
return
|
||||
}
|
||||
sc.pingOut++
|
||||
if sc.pingOut > sc.pingMaxOut {
|
||||
sc.pingMu.Unlock()
|
||||
sc.closeDueToPing(ErrMaxPings)
|
||||
return
|
||||
}
|
||||
sc.pingTimer.Reset(sc.pingInterval)
|
||||
nc := sc.nc
|
||||
sc.pingMu.Unlock()
|
||||
// Send the PING now. If the NATS connection is reported closed,
|
||||
// we are done.
|
||||
if err := nc.PublishRequest(sc.pingRequests, sc.pingInbox, sc.pingBytes); err == nats.ErrConnectionClosed {
|
||||
sc.closeDueToPing(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Receives PING responses from the server.
|
||||
// If the response contains an error message, the connection is closed
|
||||
// and the connection error callback is invoked (if one is specified).
|
||||
// If no error, the number of ping out is reset to 0. There is no
|
||||
// decrement by one since for a given PING, the client may received
|
||||
// many responses when servers are running in channel partitioning mode.
|
||||
// Regardless, any positive response from the server ought to signal
|
||||
// that the connection is ok.
|
||||
func (sc *conn) processPingResponse(m *nats.Msg) {
|
||||
// No data means OK (we don't have to call Unmarshal)
|
||||
if len(m.Data) > 0 {
|
||||
pingResp := &pb.PingResponse{}
|
||||
if err := pingResp.Unmarshal(m.Data); err != nil {
|
||||
return
|
||||
}
|
||||
if pingResp.Error != "" {
|
||||
sc.closeDueToPing(errors.New(pingResp.Error))
|
||||
return
|
||||
}
|
||||
}
|
||||
// Do not attempt to decrement, simply reset to 0.
|
||||
sc.pingMu.Lock()
|
||||
sc.pingOut = 0
|
||||
sc.pingMu.Unlock()
|
||||
}
|
||||
|
||||
// Closes a connection and invoke the connection error callback if one
|
||||
// was registered when the connection was created.
|
||||
func (sc *conn) closeDueToPing(err error) {
|
||||
sc.Lock()
|
||||
if sc.nc == nil {
|
||||
sc.Unlock()
|
||||
return
|
||||
}
|
||||
// Stop timer, unsubscribe, fail the pubs, etc..
|
||||
sc.cleanupOnClose(err)
|
||||
// No need to send Close prototol, so simply close the underlying
|
||||
// NATS connection (if we own it, and if not already closed)
|
||||
if sc.ncOwned && !sc.nc.IsClosed() {
|
||||
sc.nc.Close()
|
||||
}
|
||||
// Mark this streaming connection as closed. Do this under pingMu lock.
|
||||
sc.pingMu.Lock()
|
||||
sc.nc = nil
|
||||
sc.pingMu.Unlock()
|
||||
// Capture callback (even though this is immutable).
|
||||
cb := sc.connLostCB
|
||||
sc.Unlock()
|
||||
if cb != nil {
|
||||
// Execute in separate go routine.
|
||||
go cb(sc, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Do some cleanup when connection is lost or closed.
|
||||
// Connection lock is held on entry, and sc.nc is guaranteed not to be nil.
|
||||
func (sc *conn) cleanupOnClose(err error) {
|
||||
sc.pingMu.Lock()
|
||||
if sc.pingTimer != nil {
|
||||
sc.pingTimer.Stop()
|
||||
sc.pingTimer = nil
|
||||
}
|
||||
sc.pingMu.Unlock()
|
||||
|
||||
// Unsubscribe only if the NATS connection is not already closed...
|
||||
if !sc.nc.IsClosed() {
|
||||
if sc.ackSubscription != nil {
|
||||
sc.ackSubscription.Unsubscribe()
|
||||
}
|
||||
if sc.pingSub != nil {
|
||||
sc.pingSub.Unsubscribe()
|
||||
}
|
||||
}
|
||||
// Fail all pending pubs
|
||||
for guid, pubAck := range sc.pubAckMap {
|
||||
if pubAck.t != nil {
|
||||
pubAck.t.Stop()
|
||||
}
|
||||
if pubAck.ah != nil {
|
||||
pubAck.ah(guid, err)
|
||||
} else if pubAck.ch != nil {
|
||||
pubAck.ch <- err
|
||||
}
|
||||
delete(sc.pubAckMap, guid)
|
||||
if len(sc.pubAckChan) > 0 {
|
||||
<-sc.pubAckChan
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close a connection to the stan system.
|
||||
func (sc *conn) Close() error {
|
||||
if sc == nil {
|
||||
return ErrBadConnection
|
||||
}
|
||||
|
||||
sc.Lock()
|
||||
defer sc.Unlock()
|
||||
|
||||
@ -271,13 +530,15 @@ func (sc *conn) Close() error {
|
||||
defer nc.Close()
|
||||
}
|
||||
|
||||
// Signals we are closed.
|
||||
sc.nc = nil
|
||||
|
||||
// Now close ourselves.
|
||||
if sc.ackSubscription != nil {
|
||||
sc.ackSubscription.Unsubscribe()
|
||||
}
|
||||
sc.cleanupOnClose(ErrConnectionClosed)
|
||||
|
||||
// Signals we are closed.
|
||||
// Do this also under pingMu lock so that we don't need
|
||||
// to grab sc's lock in pingServer.
|
||||
sc.pingMu.Lock()
|
||||
sc.nc = nil
|
||||
sc.pingMu.Unlock()
|
||||
|
||||
req := &pb.CloseRequest{ClientID: sc.clientID}
|
||||
b, _ := req.Marshal()
|
||||
@ -303,7 +564,10 @@ func (sc *conn) Close() error {
|
||||
// closing the wrapped NATS conn will put the NATS Streaming Conn in an invalid
|
||||
// state.
|
||||
func (sc *conn) NatsConn() *nats.Conn {
|
||||
return sc.nc
|
||||
sc.RLock()
|
||||
nc := sc.nc
|
||||
sc.RUnlock()
|
||||
return nc
|
||||
}
|
||||
|
||||
// Process a heartbeat from the NATS Streaming cluster
|
||||
@ -322,9 +586,7 @@ func (sc *conn) processAck(m *nats.Msg) {
|
||||
pa := &pb.PubAck{}
|
||||
err := pa.Unmarshal(m.Data)
|
||||
if err != nil {
|
||||
// FIXME, make closure to have context?
|
||||
fmt.Printf("Error processing unmarshal\n")
|
||||
return
|
||||
panic(fmt.Errorf("Error during ack unmarshal: %v", err))
|
||||
}
|
||||
|
||||
// Remove
|
||||
@ -346,7 +608,10 @@ func (sc *conn) processAck(m *nats.Msg) {
|
||||
|
||||
// Publish will publish to the cluster and wait for an ACK.
|
||||
func (sc *conn) Publish(subject string, data []byte) error {
|
||||
ch := make(chan error)
|
||||
// Need to make this a buffered channel of 1 in case
|
||||
// a publish call is blocked in pubAckChan but cleanupOnClose()
|
||||
// is trying to push the error to this channel.
|
||||
ch := make(chan error, 1)
|
||||
_, err := sc.publishAsync(subject, data, nil, ch)
|
||||
if err == nil {
|
||||
err = <-ch
|
||||
@ -370,9 +635,11 @@ func (sc *conn) publishAsync(subject string, data []byte, ah AckHandler, ch chan
|
||||
|
||||
subj := sc.pubPrefix + "." + subject
|
||||
// This is only what we need from PubMsg in the timer below,
|
||||
// so do this so that pe doesn't escape (and we same on new object)
|
||||
peGUID := nuid.Next()
|
||||
pe := &pb.PubMsg{ClientID: sc.clientID, Guid: peGUID, Subject: subject, Data: data}
|
||||
// so do this so that pe doesn't escape.
|
||||
peGUID := sc.pubNUID.Next()
|
||||
// We send connID regardless of server we connect to. Older server
|
||||
// will simply not decode it.
|
||||
pe := &pb.PubMsg{ClientID: sc.clientID, Guid: peGUID, Subject: subject, Data: data, ConnID: sc.connID}
|
||||
b, _ := pe.Marshal()
|
||||
|
||||
// Map ack to guid.
|
||||
@ -381,25 +648,44 @@ func (sc *conn) publishAsync(subject string, data []byte, ah AckHandler, ch chan
|
||||
ackSubject := sc.ackSubject
|
||||
ackTimeout := sc.opts.AckTimeout
|
||||
pac := sc.pubAckChan
|
||||
nc := sc.nc
|
||||
sc.Unlock()
|
||||
|
||||
// Use the buffered channel to control the number of outstanding acks.
|
||||
pac <- struct{}{}
|
||||
|
||||
err := sc.nc.PublishRequest(subj, ackSubject, b)
|
||||
if err != nil {
|
||||
sc.removeAck(peGUID)
|
||||
return "", err
|
||||
}
|
||||
err := nc.PublishRequest(subj, ackSubject, b)
|
||||
|
||||
// Setup the timer for expiration.
|
||||
sc.Lock()
|
||||
if err != nil || sc.nc == nil {
|
||||
sc.Unlock()
|
||||
// If we got and error on publish or the connection has been closed,
|
||||
// we need to return an error only if:
|
||||
// - we can remove the pubAck from the map
|
||||
// - we can't, but this is an async pub with no provided AckHandler
|
||||
removed := sc.removeAck(peGUID) != nil
|
||||
if removed || (ch == nil && ah == nil) {
|
||||
if err == nil {
|
||||
err = ErrConnectionClosed
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
// pubAck was removed from cleanupOnClose() and error will be sent
|
||||
// to appropriate go channel (ah or ch).
|
||||
return peGUID, nil
|
||||
}
|
||||
a.t = time.AfterFunc(ackTimeout, func() {
|
||||
sc.removeAck(peGUID)
|
||||
if a.ah != nil {
|
||||
ah(peGUID, ErrTimeout)
|
||||
pubAck := sc.removeAck(peGUID)
|
||||
// processAck could get here before and handle the ack.
|
||||
// If that's the case, we would get nil here and simply return.
|
||||
if pubAck == nil {
|
||||
return
|
||||
}
|
||||
if pubAck.ah != nil {
|
||||
pubAck.ah(peGUID, ErrTimeout)
|
||||
} else if a.ch != nil {
|
||||
a.ch <- ErrTimeout
|
||||
pubAck.ch <- ErrTimeout
|
||||
}
|
||||
})
|
||||
sc.Unlock()
|
||||
@ -436,7 +722,7 @@ func (sc *conn) processMsg(raw *nats.Msg) {
|
||||
msg := &Msg{}
|
||||
err := msg.Unmarshal(raw.Data)
|
||||
if err != nil {
|
||||
panic("Error processing unmarshal for msg")
|
||||
panic(fmt.Errorf("Error processing unmarshal for msg: %v", err))
|
||||
}
|
||||
// Lookup the subscription
|
||||
sc.RLock()
|
||||
@ -465,12 +751,11 @@ func (sc *conn) processMsg(raw *nats.Msg) {
|
||||
cb(msg)
|
||||
}
|
||||
|
||||
// Proces auto-ack
|
||||
// Process auto-ack
|
||||
if !isManualAck && nc != nil {
|
||||
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
||||
b, _ := ack.Marshal()
|
||||
if err := nc.Publish(ackSubject, b); err != nil {
|
||||
// FIXME(dlc) - Async error handler? Retry?
|
||||
}
|
||||
// FIXME(dlc) - Async error handler? Retry?
|
||||
nc.Publish(ackSubject, b)
|
||||
}
|
||||
}
|
||||
|
1476
gateway/vendor/github.com/nats-io/go-nats-streaming/stan_test.go
generated
vendored
1476
gateway/vendor/github.com/nats-io/go-nats-streaming/stan_test.go
generated
vendored
File diff suppressed because it is too large
Load Diff
128
gateway/vendor/github.com/nats-io/go-nats-streaming/sub.go
generated
vendored
128
gateway/vendor/github.com/nats-io/go-nats-streaming/sub.go
generated
vendored
@ -1,4 +1,15 @@
|
||||
// Copyright 2016 Apcera Inc. All rights reserved.
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package stan is a Go client for the NATS Streaming messaging system (https://nats.io).
|
||||
package stan
|
||||
@ -30,6 +41,14 @@ type Msg struct {
|
||||
// Subscription represents a subscription within the NATS Streaming cluster. Subscriptions
|
||||
// will be rate matched and follow at-least delivery semantics.
|
||||
type Subscription interface {
|
||||
ClearMaxPending() error
|
||||
Delivered() (int64, error)
|
||||
Dropped() (int, error)
|
||||
IsValid() bool
|
||||
MaxPending() (int, int, error)
|
||||
Pending() (int, int, error)
|
||||
PendingLimits() (int, int, error)
|
||||
SetPendingLimits(msgLimit, bytesLimit int) error
|
||||
// Unsubscribe removes interest in the subscription.
|
||||
// For durables, it means that the durable interest is also removed from
|
||||
// the server. Restarting a durable with the same name will not resume
|
||||
@ -256,12 +275,97 @@ func (sc *conn) subscribe(subject, qgroup string, cb MsgHandler, options ...Subs
|
||||
return sub, nil
|
||||
}
|
||||
|
||||
// ClearMaxPending resets the maximums seen so far.
|
||||
func (sub *subscription) ClearMaxPending() error {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.ClearMaxPending()
|
||||
}
|
||||
|
||||
// Delivered returns the number of delivered messages for this subscription.
|
||||
func (sub *subscription) Delivered() (int64, error) {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return -1, ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.Delivered()
|
||||
}
|
||||
|
||||
// Dropped returns the number of known dropped messages for this subscription.
|
||||
// This will correspond to messages dropped by violations of PendingLimits. If
|
||||
// the server declares the connection a SlowConsumer, this number may not be
|
||||
// valid.
|
||||
func (sub *subscription) Dropped() (int, error) {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return -1, ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.Dropped()
|
||||
}
|
||||
|
||||
// IsValid returns a boolean indicating whether the subscription
|
||||
// is still active. This will return false if the subscription has
|
||||
// already been closed.
|
||||
func (sub *subscription) IsValid() bool {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return false
|
||||
}
|
||||
return sub.inboxSub.IsValid()
|
||||
}
|
||||
|
||||
// MaxPending returns the maximum number of queued messages and queued bytes seen so far.
|
||||
func (sub *subscription) MaxPending() (int, int, error) {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return -1, -1, ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.MaxPending()
|
||||
}
|
||||
|
||||
// Pending returns the number of queued messages and queued bytes in the client for this subscription.
|
||||
func (sub *subscription) Pending() (int, int, error) {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return -1, -1, ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.Pending()
|
||||
}
|
||||
|
||||
// PendingLimits returns the current limits for this subscription.
|
||||
// If no error is returned, a negative value indicates that the
|
||||
// given metric is not limited.
|
||||
func (sub *subscription) PendingLimits() (int, int, error) {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return -1, -1, ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.PendingLimits()
|
||||
}
|
||||
|
||||
// SetPendingLimits sets the limits for pending msgs and bytes for this subscription.
|
||||
// Zero is not allowed. Any negative value means that the given metric is not limited.
|
||||
func (sub *subscription) SetPendingLimits(msgLimit, bytesLimit int) error {
|
||||
sub.Lock()
|
||||
defer sub.Unlock()
|
||||
if sub.inboxSub == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
return sub.inboxSub.SetPendingLimits(msgLimit, bytesLimit)
|
||||
}
|
||||
|
||||
// closeOrUnsubscribe performs either close or unsubsribe based on
|
||||
// given boolean.
|
||||
func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
|
||||
if sub == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
sub.Lock()
|
||||
sc := sub.sc
|
||||
if sc == nil {
|
||||
@ -274,10 +378,6 @@ func (sub *subscription) closeOrUnsubscribe(doClose bool) error {
|
||||
sub.inboxSub = nil
|
||||
sub.Unlock()
|
||||
|
||||
if sc == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
|
||||
sc.Lock()
|
||||
if sc.nc == nil {
|
||||
sc.Unlock()
|
||||
@ -342,12 +442,8 @@ func (msg *Msg) Ack() error {
|
||||
if msg == nil {
|
||||
return ErrNilMsg
|
||||
}
|
||||
// Look up subscription
|
||||
// Look up subscription (cannot be nil)
|
||||
sub := msg.Sub.(*subscription)
|
||||
if sub == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
|
||||
sub.RLock()
|
||||
ackSubject := sub.ackInbox
|
||||
isManualAck := sub.opts.ManualAcks
|
||||
@ -355,6 +451,9 @@ func (msg *Msg) Ack() error {
|
||||
sub.RUnlock()
|
||||
|
||||
// Check for error conditions.
|
||||
if !isManualAck {
|
||||
return ErrManualAck
|
||||
}
|
||||
if sc == nil {
|
||||
return ErrBadSubscription
|
||||
}
|
||||
@ -365,9 +464,6 @@ func (msg *Msg) Ack() error {
|
||||
if nc == nil {
|
||||
return ErrBadConnection
|
||||
}
|
||||
if !isManualAck {
|
||||
return ErrManualAck
|
||||
}
|
||||
|
||||
// Ack here.
|
||||
ack := &pb.Ack{Subject: msg.Subject, Sequence: msg.Sequence}
|
||||
|
Reference in New Issue
Block a user