mirror of
https://github.com/crazy-max/diun.git
synced 2025-12-21 13:23:09 +01:00
switch to github.com/rabbitmq/amqp091-go module
This commit is contained in:
2
go.mod
2
go.mod
@@ -34,10 +34,10 @@ require (
|
||||
github.com/panjf2000/ants/v2 v2.10.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pkg/profile v1.7.0
|
||||
github.com/rabbitmq/amqp091-go v1.10.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/russross/blackfriday/v2 v2.1.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/streadway/amqp v1.1.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/tidwall/pretty v1.2.1
|
||||
go.etcd.io/bbolt v1.3.10
|
||||
|
||||
6
go.sum
6
go.sum
@@ -281,6 +281,8 @@ github.com/prometheus/common v0.51.1 h1:eIjN50Bwglz6a/c3hAgSMcofL3nD+nFQkV6Dd4Ds
|
||||
github.com/prometheus/common v0.51.1/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
||||
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
@@ -301,8 +303,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo=
|
||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM=
|
||||
github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
|
||||
github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@@ -348,6 +348,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/crypto v0.0.0-20181029175232-7e6ffbd03851/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/crazy-max/diun/v4/internal/msg"
|
||||
"github.com/crazy-max/diun/v4/internal/notif/notifier"
|
||||
"github.com/crazy-max/diun/v4/pkg/utl"
|
||||
"github.com/streadway/amqp"
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
)
|
||||
|
||||
// Client represents an active amqp notification object
|
||||
|
||||
6
vendor/github.com/rabbitmq/amqp091-go/.gitignore
generated
vendored
Normal file
6
vendor/github.com/rabbitmq/amqp091-go/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
certs/*
|
||||
spec/spec
|
||||
examples/simple-consumer/simple-consumer
|
||||
examples/simple-producer/simple-producer
|
||||
|
||||
.idea/
|
||||
3
vendor/github.com/rabbitmq/amqp091-go/.golangci.yml
generated
vendored
Normal file
3
vendor/github.com/rabbitmq/amqp091-go/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
run:
|
||||
build-tags:
|
||||
- integration
|
||||
363
vendor/github.com/rabbitmq/amqp091-go/CHANGELOG.md
generated
vendored
Normal file
363
vendor/github.com/rabbitmq/amqp091-go/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,363 @@
|
||||
# Changelog
|
||||
|
||||
## [v1.10.0](https://github.com/rabbitmq/amqp091-go/tree/v1.10.0) (2024-05-08)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.9.0...v1.10.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Undeprecate non-context publish functions [\#259](https://github.com/rabbitmq/amqp091-go/pull/259) ([Zerpet](https://github.com/Zerpet))
|
||||
- Update Go directive [\#257](https://github.com/rabbitmq/amqp091-go/pull/257) ([Zerpet](https://github.com/Zerpet))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- republishing on reconnect bug in the example [\#249](https://github.com/rabbitmq/amqp091-go/issues/249)
|
||||
- Channel Notify Close not receive event when connection is closed by RMQ server. [\#241](https://github.com/rabbitmq/amqp091-go/issues/241)
|
||||
- Inconsistent documentation [\#231](https://github.com/rabbitmq/amqp091-go/issues/231)
|
||||
- Data race in the client example [\#72](https://github.com/rabbitmq/amqp091-go/issues/72)
|
||||
- Fix string function of URI [\#258](https://github.com/rabbitmq/amqp091-go/pull/258) ([Zerpet](https://github.com/Zerpet))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Documentation needed \(`PublishWithContext` does not use context\) [\#195](https://github.com/rabbitmq/amqp091-go/issues/195)
|
||||
- concurrent dispatch data race [\#226](https://github.com/rabbitmq/amqp091-go/issues/226)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix data race in example [\#260](https://github.com/rabbitmq/amqp091-go/pull/260) ([Zerpet](https://github.com/Zerpet))
|
||||
- Address CodeQL warning [\#252](https://github.com/rabbitmq/amqp091-go/pull/252) ([lukebakken](https://github.com/lukebakken))
|
||||
- Add support for additional AMQP URI query parameters [\#251](https://github.com/rabbitmq/amqp091-go/pull/251) ([vilius-g](https://github.com/vilius-g))
|
||||
- Example fix [\#250](https://github.com/rabbitmq/amqp091-go/pull/250) ([Boris-Plato](https://github.com/Boris-Plato))
|
||||
- Increasing the code coverage [\#248](https://github.com/rabbitmq/amqp091-go/pull/248) ([edercarloscosta](https://github.com/edercarloscosta))
|
||||
- Use correct mutex to guard confirms.published [\#240](https://github.com/rabbitmq/amqp091-go/pull/240) ([hjr265](https://github.com/hjr265))
|
||||
- Documenting Publishing.Expiration usage [\#232](https://github.com/rabbitmq/amqp091-go/pull/232) ([niksteff](https://github.com/niksteff))
|
||||
- fix comment typo in example\_client\_test.go [\#228](https://github.com/rabbitmq/amqp091-go/pull/228) ([wisaTong](https://github.com/wisaTong))
|
||||
- Bump go.uber.org/goleak from 1.2.1 to 1.3.0 [\#227](https://github.com/rabbitmq/amqp091-go/pull/227) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
|
||||
## [v1.9.0](https://github.com/rabbitmq/amqp091-go/tree/v1.9.0) (2023-10-02)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.8.1...v1.9.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Use of buffered delivery channels when prefetch\_count is not null [\#200](https://github.com/rabbitmq/amqp091-go/issues/200)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- connection block when write connection reset by peer [\#222](https://github.com/rabbitmq/amqp091-go/issues/222)
|
||||
- Test failure on 32bit architectures [\#202](https://github.com/rabbitmq/amqp091-go/issues/202)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Add a constant to set consumer timeout as queue argument [\#201](https://github.com/rabbitmq/amqp091-go/issues/201)
|
||||
- Add a constant for CQ version [\#199](https://github.com/rabbitmq/amqp091-go/issues/199)
|
||||
- Examples may need to be updated after \#140 [\#153](https://github.com/rabbitmq/amqp091-go/issues/153)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update spec091.go [\#224](https://github.com/rabbitmq/amqp091-go/pull/224) ([pinkfish](https://github.com/pinkfish))
|
||||
- Closes 222 [\#223](https://github.com/rabbitmq/amqp091-go/pull/223) ([yywing](https://github.com/yywing))
|
||||
- Update write.go [\#221](https://github.com/rabbitmq/amqp091-go/pull/221) ([pinkfish](https://github.com/pinkfish))
|
||||
- Bump versions [\#219](https://github.com/rabbitmq/amqp091-go/pull/219) ([lukebakken](https://github.com/lukebakken))
|
||||
- remove extra word 'accept' from ExchangeDeclare description [\#217](https://github.com/rabbitmq/amqp091-go/pull/217) ([a-sabzian](https://github.com/a-sabzian))
|
||||
- Misc Windows CI updates [\#216](https://github.com/rabbitmq/amqp091-go/pull/216) ([lukebakken](https://github.com/lukebakken))
|
||||
- Stop using deprecated Publish function [\#207](https://github.com/rabbitmq/amqp091-go/pull/207) ([Zerpet](https://github.com/Zerpet))
|
||||
- Constant for consumer timeout queue argument [\#206](https://github.com/rabbitmq/amqp091-go/pull/206) ([Zerpet](https://github.com/Zerpet))
|
||||
- Add a constant for CQ v2 queue argument [\#205](https://github.com/rabbitmq/amqp091-go/pull/205) ([Zerpet](https://github.com/Zerpet))
|
||||
- Fix example for 32-bit compatibility [\#204](https://github.com/rabbitmq/amqp091-go/pull/204) ([Zerpet](https://github.com/Zerpet))
|
||||
- Fix to increase timeout milliseconds since it's too tight [\#203](https://github.com/rabbitmq/amqp091-go/pull/203) ([t2y](https://github.com/t2y))
|
||||
- Add Channel.ConsumeWithContext to be able to cancel delivering [\#192](https://github.com/rabbitmq/amqp091-go/pull/192) ([t2y](https://github.com/t2y))
|
||||
|
||||
## [v1.8.1](https://github.com/rabbitmq/amqp091-go/tree/v1.8.1) (2023-05-04)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.8.0...v1.8.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Fixed incorrect version reported in client properties [52ce2efd03c53dcf77d5496977da46840e9abd24](https://github.com/rabbitmq/amqp091-go/commit/52ce2efd03c53dcf77d5496977da46840e9abd24)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix Example Client not reconnecting [\#186](https://github.com/rabbitmq/amqp091-go/pull/186) ([frankfil](https://github.com/frankfil))
|
||||
|
||||
## [v1.8.0](https://github.com/rabbitmq/amqp091-go/tree/v1.8.0) (2023-03-21)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.7.0...v1.8.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- memory leak [\#179](https://github.com/rabbitmq/amqp091-go/issues/179)
|
||||
- the publishWithContext interface will not return when it times out [\#178](https://github.com/rabbitmq/amqp091-go/issues/178)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix race condition on confirms [\#183](https://github.com/rabbitmq/amqp091-go/pull/183) ([calloway-jacob](https://github.com/calloway-jacob))
|
||||
- Add a CloseDeadline function to Connection [\#181](https://github.com/rabbitmq/amqp091-go/pull/181) ([Zerpet](https://github.com/Zerpet))
|
||||
- Fix memory leaks [\#180](https://github.com/rabbitmq/amqp091-go/pull/180) ([GXKe](https://github.com/GXKe))
|
||||
- Bump go.uber.org/goleak from 1.2.0 to 1.2.1 [\#177](https://github.com/rabbitmq/amqp091-go/pull/177) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
|
||||
## [v1.7.0](https://github.com/rabbitmq/amqp091-go/tree/v1.7.0) (2023-02-09)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.6.1...v1.7.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- \#31 resurfacing \(?\) [\#170](https://github.com/rabbitmq/amqp091-go/issues/170)
|
||||
- Deprecate QueueInspect [\#167](https://github.com/rabbitmq/amqp091-go/issues/167)
|
||||
- v1.6.0 causing rabbit connection errors [\#160](https://github.com/rabbitmq/amqp091-go/issues/160)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Set channels and allocator to nil in shutdown [\#172](https://github.com/rabbitmq/amqp091-go/pull/172) ([lukebakken](https://github.com/lukebakken))
|
||||
- Fix racing in Open [\#171](https://github.com/rabbitmq/amqp091-go/pull/171) ([Zerpet](https://github.com/Zerpet))
|
||||
- adding go 1.20 to tests [\#169](https://github.com/rabbitmq/amqp091-go/pull/169) ([halilylm](https://github.com/halilylm))
|
||||
- Deprecate the QueueInspect function [\#168](https://github.com/rabbitmq/amqp091-go/pull/168) ([lukebakken](https://github.com/lukebakken))
|
||||
- Check if channel is nil before updating it [\#150](https://github.com/rabbitmq/amqp091-go/pull/150) ([julienschmidt](https://github.com/julienschmidt))
|
||||
|
||||
## [v1.6.1](https://github.com/rabbitmq/amqp091-go/tree/v1.6.1) (2023-02-01)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.6.1-rc.2...v1.6.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update Makefile targets related to RabbitMQ [\#163](https://github.com/rabbitmq/amqp091-go/pull/163) ([Zerpet](https://github.com/Zerpet))
|
||||
|
||||
## [v1.6.1-rc.2](https://github.com/rabbitmq/amqp091-go/tree/v1.6.1-rc.2) (2023-01-31)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.6.1-rc.1...v1.6.1-rc.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Do not overly protect writes [\#162](https://github.com/rabbitmq/amqp091-go/pull/162) ([lukebakken](https://github.com/lukebakken))
|
||||
|
||||
## [v1.6.1-rc.1](https://github.com/rabbitmq/amqp091-go/tree/v1.6.1-rc.1) (2023-01-31)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.6.0...v1.6.1-rc.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Calling Channel\(\) on an empty connection panics [\#148](https://github.com/rabbitmq/amqp091-go/issues/148)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Ensure flush happens and correctly lock connection for a series of unflushed writes [\#161](https://github.com/rabbitmq/amqp091-go/pull/161) ([lukebakken](https://github.com/lukebakken))
|
||||
|
||||
## [v1.6.0](https://github.com/rabbitmq/amqp091-go/tree/v1.6.0) (2023-01-20)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.5.0...v1.6.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Add constants for Queue arguments [\#145](https://github.com/rabbitmq/amqp091-go/pull/145) ([Zerpet](https://github.com/Zerpet))
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- README not up to date [\#154](https://github.com/rabbitmq/amqp091-go/issues/154)
|
||||
- Allow re-using default connection config \(custom properties\) [\#152](https://github.com/rabbitmq/amqp091-go/issues/152)
|
||||
- Rename package name to amqp in V2 [\#151](https://github.com/rabbitmq/amqp091-go/issues/151)
|
||||
- Helper types to declare quorum queues [\#144](https://github.com/rabbitmq/amqp091-go/issues/144)
|
||||
- Inefficient use of buffers reduces potential throughput for basicPublish with small messages. [\#141](https://github.com/rabbitmq/amqp091-go/issues/141)
|
||||
- bug, close cause panic [\#130](https://github.com/rabbitmq/amqp091-go/issues/130)
|
||||
- Publishing Headers are unable to store Table with slice values [\#125](https://github.com/rabbitmq/amqp091-go/issues/125)
|
||||
- Example client can deadlock in Close due to unconsumed confirmations [\#122](https://github.com/rabbitmq/amqp091-go/issues/122)
|
||||
- SAC not working properly [\#106](https://github.com/rabbitmq/amqp091-go/issues/106)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add automatic CHANGELOG.md generation [\#158](https://github.com/rabbitmq/amqp091-go/pull/158) ([lukebakken](https://github.com/lukebakken))
|
||||
- Supply library-defined props with NewConnectionProperties [\#157](https://github.com/rabbitmq/amqp091-go/pull/157) ([slagiewka](https://github.com/slagiewka))
|
||||
- Fix linter warnings [\#156](https://github.com/rabbitmq/amqp091-go/pull/156) ([Zerpet](https://github.com/Zerpet))
|
||||
- Remove outdated information from README [\#155](https://github.com/rabbitmq/amqp091-go/pull/155) ([scriptcoded](https://github.com/scriptcoded))
|
||||
- Add example producer using DeferredConfirm [\#149](https://github.com/rabbitmq/amqp091-go/pull/149) ([Zerpet](https://github.com/Zerpet))
|
||||
- Ensure code is formatted [\#147](https://github.com/rabbitmq/amqp091-go/pull/147) ([lukebakken](https://github.com/lukebakken))
|
||||
- Fix inefficient use of buffers that reduces the potential throughput of basicPublish [\#142](https://github.com/rabbitmq/amqp091-go/pull/142) ([fadams](https://github.com/fadams))
|
||||
- Do not embed context in DeferredConfirmation [\#140](https://github.com/rabbitmq/amqp091-go/pull/140) ([tie](https://github.com/tie))
|
||||
- Add constant for default exchange [\#139](https://github.com/rabbitmq/amqp091-go/pull/139) ([marlongerson](https://github.com/marlongerson))
|
||||
- Fix indentation and remove unnecessary instructions [\#138](https://github.com/rabbitmq/amqp091-go/pull/138) ([alraujo](https://github.com/alraujo))
|
||||
- Remove unnecessary instruction [\#135](https://github.com/rabbitmq/amqp091-go/pull/135) ([alraujo](https://github.com/alraujo))
|
||||
- Fix example client to avoid deadlock in Close [\#123](https://github.com/rabbitmq/amqp091-go/pull/123) ([Zerpet](https://github.com/Zerpet))
|
||||
- Bump go.uber.org/goleak from 1.1.12 to 1.2.0 [\#116](https://github.com/rabbitmq/amqp091-go/pull/116) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||
|
||||
## [v1.5.0](https://github.com/rabbitmq/amqp091-go/tree/v1.5.0) (2022-09-07)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.4.0...v1.5.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Provide a friendly way to set connection name [\#105](https://github.com/rabbitmq/amqp091-go/issues/105)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Support connection.update-secret [\#107](https://github.com/rabbitmq/amqp091-go/issues/107)
|
||||
- Example Client: Implementation of a Consumer with reconnection support [\#40](https://github.com/rabbitmq/amqp091-go/issues/40)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- use PublishWithContext instead of Publish [\#115](https://github.com/rabbitmq/amqp091-go/pull/115) ([Gsantomaggio](https://github.com/Gsantomaggio))
|
||||
- Add support for connection.update-secret [\#114](https://github.com/rabbitmq/amqp091-go/pull/114) ([Zerpet](https://github.com/Zerpet))
|
||||
- Remove warning on RabbitMQ tutorials in go [\#113](https://github.com/rabbitmq/amqp091-go/pull/113) ([ChunyiLyu](https://github.com/ChunyiLyu))
|
||||
- Update AMQP Spec [\#110](https://github.com/rabbitmq/amqp091-go/pull/110) ([Zerpet](https://github.com/Zerpet))
|
||||
- Add an example of reliable consumer [\#109](https://github.com/rabbitmq/amqp091-go/pull/109) ([Zerpet](https://github.com/Zerpet))
|
||||
- Add convenience function to set connection name [\#108](https://github.com/rabbitmq/amqp091-go/pull/108) ([Zerpet](https://github.com/Zerpet))
|
||||
|
||||
## [v1.4.0](https://github.com/rabbitmq/amqp091-go/tree/v1.4.0) (2022-07-19)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.3.4...v1.4.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- target machine actively refused connection [\#99](https://github.com/rabbitmq/amqp091-go/issues/99)
|
||||
- 504 channel/connection is not open error occurred in multiple connection with same rabbitmq service [\#97](https://github.com/rabbitmq/amqp091-go/issues/97)
|
||||
- Add possible cancel of DeferredConfirmation [\#92](https://github.com/rabbitmq/amqp091-go/issues/92)
|
||||
- Documentation [\#89](https://github.com/rabbitmq/amqp091-go/issues/89)
|
||||
- Channel Close gets stuck after closing a connection \(via management UI\) [\#88](https://github.com/rabbitmq/amqp091-go/issues/88)
|
||||
- this library has same issue [\#83](https://github.com/rabbitmq/amqp091-go/issues/83)
|
||||
- Provide a logging interface [\#81](https://github.com/rabbitmq/amqp091-go/issues/81)
|
||||
- 1.4.0 release checklist [\#77](https://github.com/rabbitmq/amqp091-go/issues/77)
|
||||
- Data race in the client example [\#72](https://github.com/rabbitmq/amqp091-go/issues/72)
|
||||
- reader go routine hangs and leaks when Connection.Close\(\) is called multiple times [\#69](https://github.com/rabbitmq/amqp091-go/issues/69)
|
||||
- Support auto-reconnect and cluster [\#65](https://github.com/rabbitmq/amqp091-go/issues/65)
|
||||
- Connection/Channel Deadlock [\#32](https://github.com/rabbitmq/amqp091-go/issues/32)
|
||||
- Closing connection and/or channel hangs NotifyPublish is used [\#21](https://github.com/rabbitmq/amqp091-go/issues/21)
|
||||
- Consumer channel isn't closed in the event of unexpected disconnection [\#18](https://github.com/rabbitmq/amqp091-go/issues/18)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- fix race condition with context close and confirm at the same time on DeferredConfirmation. [\#101](https://github.com/rabbitmq/amqp091-go/pull/101) ([sapk](https://github.com/sapk))
|
||||
- Add build TLS config from URI [\#98](https://github.com/rabbitmq/amqp091-go/pull/98) ([reddec](https://github.com/reddec))
|
||||
- Use context for Publish methods [\#96](https://github.com/rabbitmq/amqp091-go/pull/96) ([sapk](https://github.com/sapk))
|
||||
- Added function to get the remote peer's IP address \(conn.RemoteAddr\(\)\) [\#95](https://github.com/rabbitmq/amqp091-go/pull/95) ([rabb1t](https://github.com/rabb1t))
|
||||
- Update connection documentation [\#90](https://github.com/rabbitmq/amqp091-go/pull/90) ([Zerpet](https://github.com/Zerpet))
|
||||
- Revert test to demonstrate actual bug [\#87](https://github.com/rabbitmq/amqp091-go/pull/87) ([lukebakken](https://github.com/lukebakken))
|
||||
- Minor improvements to examples [\#86](https://github.com/rabbitmq/amqp091-go/pull/86) ([lukebakken](https://github.com/lukebakken))
|
||||
- Do not skip flaky test in CI [\#85](https://github.com/rabbitmq/amqp091-go/pull/85) ([lukebakken](https://github.com/lukebakken))
|
||||
- Add logging [\#84](https://github.com/rabbitmq/amqp091-go/pull/84) ([lukebakken](https://github.com/lukebakken))
|
||||
- Add a win32 build [\#82](https://github.com/rabbitmq/amqp091-go/pull/82) ([lukebakken](https://github.com/lukebakken))
|
||||
- channel: return nothing instead of always a nil-error in receive methods [\#80](https://github.com/rabbitmq/amqp091-go/pull/80) ([fho](https://github.com/fho))
|
||||
- update the contributing & readme files, improve makefile [\#79](https://github.com/rabbitmq/amqp091-go/pull/79) ([fho](https://github.com/fho))
|
||||
- Fix lint errors [\#78](https://github.com/rabbitmq/amqp091-go/pull/78) ([lukebakken](https://github.com/lukebakken))
|
||||
- ci: run golangci-lint [\#76](https://github.com/rabbitmq/amqp091-go/pull/76) ([fho](https://github.com/fho))
|
||||
- ci: run test via make & remove travis CI config [\#75](https://github.com/rabbitmq/amqp091-go/pull/75) ([fho](https://github.com/fho))
|
||||
- ci: run tests with race detector [\#74](https://github.com/rabbitmq/amqp091-go/pull/74) ([fho](https://github.com/fho))
|
||||
- Detect go routine leaks in integration testcases [\#73](https://github.com/rabbitmq/amqp091-go/pull/73) ([fho](https://github.com/fho))
|
||||
- connection: fix: reader go-routine is leaked on connection close [\#70](https://github.com/rabbitmq/amqp091-go/pull/70) ([fho](https://github.com/fho))
|
||||
- adding best practises for NotifyPublish for issue\_21 scenario [\#68](https://github.com/rabbitmq/amqp091-go/pull/68) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- Update Go version [\#67](https://github.com/rabbitmq/amqp091-go/pull/67) ([Zerpet](https://github.com/Zerpet))
|
||||
- Regenerate certs with SHA256 to fix test with Go 1.18+ [\#66](https://github.com/rabbitmq/amqp091-go/pull/66) ([anthonyfok](https://github.com/anthonyfok))
|
||||
|
||||
## [v1.3.4](https://github.com/rabbitmq/amqp091-go/tree/v1.3.4) (2022-04-01)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.3.3...v1.3.4)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- bump version to 1.3.4 [\#63](https://github.com/rabbitmq/amqp091-go/pull/63) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- updating doc [\#62](https://github.com/rabbitmq/amqp091-go/pull/62) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
|
||||
## [v1.3.3](https://github.com/rabbitmq/amqp091-go/tree/v1.3.3) (2022-04-01)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.3.2...v1.3.3)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Add Client Version [\#49](https://github.com/rabbitmq/amqp091-go/issues/49)
|
||||
- OpenTelemetry Propagation [\#22](https://github.com/rabbitmq/amqp091-go/issues/22)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- bump buildVersion for release [\#61](https://github.com/rabbitmq/amqp091-go/pull/61) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- adding documentation for notifyClose best pratices [\#60](https://github.com/rabbitmq/amqp091-go/pull/60) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- adding documentation on NotifyClose of connection and channel to enfo… [\#59](https://github.com/rabbitmq/amqp091-go/pull/59) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
|
||||
## [v1.3.2](https://github.com/rabbitmq/amqp091-go/tree/v1.3.2) (2022-03-28)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.3.1...v1.3.2)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Potential race condition in Connection module [\#31](https://github.com/rabbitmq/amqp091-go/issues/31)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- bump versioning to 1.3.2 [\#58](https://github.com/rabbitmq/amqp091-go/pull/58) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
|
||||
## [v1.3.1](https://github.com/rabbitmq/amqp091-go/tree/v1.3.1) (2022-03-25)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.3.0...v1.3.1)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Possible deadlock on DeferredConfirmation.Wait\(\) [\#46](https://github.com/rabbitmq/amqp091-go/issues/46)
|
||||
- Call to Delivery.Ack blocks indefinitely in case of disconnection [\#19](https://github.com/rabbitmq/amqp091-go/issues/19)
|
||||
- Unexpacted behavor of channel.IsClosed\(\) [\#14](https://github.com/rabbitmq/amqp091-go/issues/14)
|
||||
- A possible dead lock in connection close notification Go channel [\#11](https://github.com/rabbitmq/amqp091-go/issues/11)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- These ones were the ones testing Open scenarios. The issue is that Op… [\#57](https://github.com/rabbitmq/amqp091-go/pull/57) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- changing defaultVersion to buildVersion and create a simple change\_ve… [\#54](https://github.com/rabbitmq/amqp091-go/pull/54) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- adding integration test for issue 11 [\#50](https://github.com/rabbitmq/amqp091-go/pull/50) ([DanielePalaia](https://github.com/DanielePalaia))
|
||||
- Remove the old link product [\#48](https://github.com/rabbitmq/amqp091-go/pull/48) ([Gsantomaggio](https://github.com/Gsantomaggio))
|
||||
- Fix deadlock on DeferredConfirmations [\#47](https://github.com/rabbitmq/amqp091-go/pull/47) ([SpencerTorres](https://github.com/SpencerTorres))
|
||||
- Example client: Rename Stream\(\) to Consume\(\) to avoid confusion with RabbitMQ streams [\#39](https://github.com/rabbitmq/amqp091-go/pull/39) ([andygrunwald](https://github.com/andygrunwald))
|
||||
- Example client: Rename `name` to `queueName` to make the usage clear and explicit [\#38](https://github.com/rabbitmq/amqp091-go/pull/38) ([andygrunwald](https://github.com/andygrunwald))
|
||||
- Client example: Renamed concept "Session" to "Client" [\#37](https://github.com/rabbitmq/amqp091-go/pull/37) ([andygrunwald](https://github.com/andygrunwald))
|
||||
- delete unuseful code [\#36](https://github.com/rabbitmq/amqp091-go/pull/36) ([liutaot](https://github.com/liutaot))
|
||||
- Client Example: Fix closing order [\#35](https://github.com/rabbitmq/amqp091-go/pull/35) ([andygrunwald](https://github.com/andygrunwald))
|
||||
- Client example: Use instance logger instead of global logger [\#34](https://github.com/rabbitmq/amqp091-go/pull/34) ([andygrunwald](https://github.com/andygrunwald))
|
||||
|
||||
## [v1.3.0](https://github.com/rabbitmq/amqp091-go/tree/v1.3.0) (2022-01-13)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.2.0...v1.3.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- documentation of changes triggering version updates [\#29](https://github.com/rabbitmq/amqp091-go/issues/29)
|
||||
- Persistent messages folder [\#27](https://github.com/rabbitmq/amqp091-go/issues/27)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Expose a method to enable out-of-order Publisher Confirms [\#33](https://github.com/rabbitmq/amqp091-go/pull/33) ([benmoss](https://github.com/benmoss))
|
||||
- Fix Signed 8-bit headers being treated as unsigned [\#26](https://github.com/rabbitmq/amqp091-go/pull/26) ([alex-goodisman](https://github.com/alex-goodisman))
|
||||
|
||||
## [v1.2.0](https://github.com/rabbitmq/amqp091-go/tree/v1.2.0) (2021-11-17)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/v1.1.0...v1.2.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- No access to this vhost [\#24](https://github.com/rabbitmq/amqp091-go/issues/24)
|
||||
- copyright issue? [\#12](https://github.com/rabbitmq/amqp091-go/issues/12)
|
||||
- A possible dead lock when publishing message with confirmation [\#10](https://github.com/rabbitmq/amqp091-go/issues/10)
|
||||
- Semver release [\#7](https://github.com/rabbitmq/amqp091-go/issues/7)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix deadlock between publishing and receiving confirms [\#25](https://github.com/rabbitmq/amqp091-go/pull/25) ([benmoss](https://github.com/benmoss))
|
||||
- Add GetNextPublishSeqNo for channel in confirm mode [\#23](https://github.com/rabbitmq/amqp091-go/pull/23) ([kamal-github](https://github.com/kamal-github))
|
||||
- Added support for cert-only login without user and password [\#20](https://github.com/rabbitmq/amqp091-go/pull/20) ([mihaitodor](https://github.com/mihaitodor))
|
||||
|
||||
## [v1.1.0](https://github.com/rabbitmq/amqp091-go/tree/v1.1.0) (2021-09-21)
|
||||
|
||||
[Full Changelog](https://github.com/rabbitmq/amqp091-go/compare/ebd83429aa8cb06fa569473f623e87675f96d3a9...v1.1.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- AMQPLAIN authentication does not work [\#15](https://github.com/rabbitmq/amqp091-go/issues/15)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix AMQPLAIN authentication mechanism [\#16](https://github.com/rabbitmq/amqp091-go/pull/16) ([hodbn](https://github.com/hodbn))
|
||||
- connection: clarify documented behavior of NotifyClose [\#13](https://github.com/rabbitmq/amqp091-go/pull/13) ([pabigot](https://github.com/pabigot))
|
||||
- Add a link to pkg.go.dev API docs [\#9](https://github.com/rabbitmq/amqp091-go/pull/9) ([benmoss](https://github.com/benmoss))
|
||||
- add test go version 1.16.x and 1.17.x [\#8](https://github.com/rabbitmq/amqp091-go/pull/8) ([k4n4ry](https://github.com/k4n4ry))
|
||||
- fix typos [\#6](https://github.com/rabbitmq/amqp091-go/pull/6) ([h44z](https://github.com/h44z))
|
||||
- Heartbeat interval should be timeout/2 [\#5](https://github.com/rabbitmq/amqp091-go/pull/5) ([ifo20](https://github.com/ifo20))
|
||||
- Exporting Channel State [\#4](https://github.com/rabbitmq/amqp091-go/pull/4) ([eibrunorodrigues](https://github.com/eibrunorodrigues))
|
||||
- Add codeql analysis [\#3](https://github.com/rabbitmq/amqp091-go/pull/3) ([MirahImage](https://github.com/MirahImage))
|
||||
- Add PR github action. [\#2](https://github.com/rabbitmq/amqp091-go/pull/2) ([MirahImage](https://github.com/MirahImage))
|
||||
- Update Copyright Statement [\#1](https://github.com/rabbitmq/amqp091-go/pull/1) ([rlewis24](https://github.com/rlewis24))
|
||||
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
||||
77
vendor/github.com/rabbitmq/amqp091-go/CODE_OF_CONDUCT.md
generated
vendored
Normal file
77
vendor/github.com/rabbitmq/amqp091-go/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in RabbitMQ Operator project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at oss-coc@vmware.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
||||
|
||||
62
vendor/github.com/rabbitmq/amqp091-go/CONTRIBUTING.md
generated
vendored
Normal file
62
vendor/github.com/rabbitmq/amqp091-go/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# Contributing
|
||||
|
||||
## Workflow
|
||||
|
||||
Here is the recommended workflow:
|
||||
|
||||
1. Fork this repository, **github.com/rabbitmq/amqp091-go**
|
||||
1. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
1. Run Static Checks
|
||||
1. Run integration tests (see below)
|
||||
1. **Implement tests**
|
||||
1. Implement fixes
|
||||
1. Commit your changes. Use a [good, descriptive, commit message][good-commit].
|
||||
1. Push to a branch (`git push -u origin my-new-feature`)
|
||||
1. Submit a pull request
|
||||
|
||||
[good-commit]: https://cbea.ms/git-commit/
|
||||
|
||||
## Running Static Checks
|
||||
|
||||
golangci-lint must be installed to run the static checks. See [installation
|
||||
docs](https://golangci-lint.run/usage/install/) for more information.
|
||||
|
||||
The static checks can be run via:
|
||||
|
||||
```shell
|
||||
make checks
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Integration Tests
|
||||
|
||||
Running the Integration tests require:
|
||||
|
||||
* A running RabbitMQ node with all defaults:
|
||||
[https://www.rabbitmq.com/download.html](https://www.rabbitmq.com/download.html)
|
||||
* That the server is either reachable via `amqp://guest:guest@127.0.0.1:5672/`
|
||||
or the environment variable `AMQP_URL` set to it's URL
|
||||
(e.g.: `export AMQP_URL="amqp://guest:verysecretpasswd@rabbitmq-host:5772/`)
|
||||
|
||||
The integration tests can be run via:
|
||||
|
||||
```shell
|
||||
make tests
|
||||
```
|
||||
|
||||
Some tests require access to `rabbitmqctl` CLI. Use the environment variable
|
||||
`RABBITMQ_RABBITMQCTL_PATH=/some/path/to/rabbitmqctl` to run those tests.
|
||||
|
||||
If you have Docker available in your machine, you can run:
|
||||
|
||||
```shell
|
||||
make tests-docker
|
||||
```
|
||||
|
||||
This target will start a RabbitMQ container, run the test suite with the environment
|
||||
variable setup, and stop RabbitMQ container after a successful run.
|
||||
|
||||
All integration tests should use the `integrationConnection(...)` test
|
||||
helpers defined in `integration_test.go` to setup the integration environment
|
||||
and logging.
|
||||
@@ -1,5 +1,7 @@
|
||||
Copyright (c) 2012-2019, Sean Treadway, SoundCloud Ltd.
|
||||
All rights reserved.
|
||||
AMQP 0-9-1 Go Client
|
||||
Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
|
||||
Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
57
vendor/github.com/rabbitmq/amqp091-go/Makefile
generated
vendored
Normal file
57
vendor/github.com/rabbitmq/amqp091-go/Makefile
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
.DEFAULT_GOAL := list
|
||||
|
||||
# Insert a comment starting with '##' after a target, and it will be printed by 'make' and 'make list'
|
||||
.PHONY: list
|
||||
list: ## list Makefile targets
|
||||
@echo "The most used targets: \n"
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: check-fmt
|
||||
check-fmt: ## Ensure code is formatted
|
||||
gofmt -l -d . # For the sake of debugging
|
||||
test -z "$$(gofmt -l .)"
|
||||
|
||||
.PHONY: fmt
|
||||
fmt: ## Run go fmt against code
|
||||
go fmt ./...
|
||||
|
||||
.PHONY: tests
|
||||
tests: ## Run all tests and requires a running rabbitmq-server. Use GO_TEST_FLAGS to add extra flags to go test
|
||||
go test -race -v -tags integration $(GO_TEST_FLAGS)
|
||||
|
||||
.PHONY: tests-docker
|
||||
tests-docker: rabbitmq-server
|
||||
RABBITMQ_RABBITMQCTL_PATH="DOCKER:$(CONTAINER_NAME)" go test -race -v -tags integration $(GO_TEST_FLAGS)
|
||||
$(MAKE) stop-rabbitmq-server
|
||||
|
||||
.PHONY: check
|
||||
check:
|
||||
golangci-lint run ./...
|
||||
|
||||
CONTAINER_NAME ?= amqp091-go-rabbitmq
|
||||
|
||||
.PHONY: rabbitmq-server
|
||||
rabbitmq-server: ## Start a RabbitMQ server using Docker. Container name can be customised with CONTAINER_NAME=some-rabbit
|
||||
docker run --detach --rm --name $(CONTAINER_NAME) \
|
||||
--publish 5672:5672 --publish 15672:15672 \
|
||||
--pull always rabbitmq:3-management
|
||||
|
||||
.PHONY: stop-rabbitmq-server
|
||||
stop-rabbitmq-server: ## Stop a RabbitMQ server using Docker. Container name can be customised with CONTAINER_NAME=some-rabbit
|
||||
docker stop $(CONTAINER_NAME)
|
||||
|
||||
certs:
|
||||
./certs.sh
|
||||
|
||||
.PHONY: certs-rm
|
||||
certs-rm:
|
||||
rm -r ./certs/
|
||||
|
||||
.PHONY: rabbitmq-server-tls
|
||||
rabbitmq-server-tls: | certs ## Start a RabbitMQ server using Docker. Container name can be customised with CONTAINER_NAME=some-rabbit
|
||||
docker run --detach --rm --name $(CONTAINER_NAME) \
|
||||
--publish 5672:5672 --publish 5671:5671 --publish 15672:15672 \
|
||||
--mount type=bind,src=./certs/server,dst=/certs \
|
||||
--mount type=bind,src=./certs/ca/cacert.pem,dst=/certs/cacert.pem,readonly \
|
||||
--mount type=bind,src=./rabbitmq-confs/tls/90-tls.conf,dst=/etc/rabbitmq/conf.d/90-tls.conf \
|
||||
--pull always rabbitmq:3-management
|
||||
105
vendor/github.com/rabbitmq/amqp091-go/README.md
generated
vendored
Normal file
105
vendor/github.com/rabbitmq/amqp091-go/README.md
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
# Go RabbitMQ Client Library
|
||||
|
||||
[](https://github.com/rabbitmq/amqp091-go/actions/workflows/tests.yml)
|
||||
[](https://pkg.go.dev/github.com/rabbitmq/amqp091-go)
|
||||
[](https://goreportcard.com/report/github.com/rabbitmq/amqp091-go)
|
||||
|
||||
This is a Go AMQP 0.9.1 client maintained by the [RabbitMQ core team](https://github.com/rabbitmq).
|
||||
It was [originally developed by Sean Treadway](https://github.com/streadway/amqp).
|
||||
|
||||
## Differences from streadway/amqp
|
||||
|
||||
Some things are different compared to the original client,
|
||||
others haven't changed.
|
||||
|
||||
### Package Name
|
||||
|
||||
This library uses a different package name. If moving from `streadway/amqp`,
|
||||
using an alias may reduce the number of changes needed:
|
||||
|
||||
``` go
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
This client uses the same 2-clause BSD license as the original project.
|
||||
|
||||
### Public API Evolution
|
||||
|
||||
This client retains key API elements as practically possible.
|
||||
It is, however, open to reasonable breaking public API changes suggested by the community.
|
||||
We don't have the "no breaking public API changes ever" rule and fully recognize
|
||||
that a good client API evolves over time.
|
||||
|
||||
|
||||
## Project Maturity
|
||||
|
||||
This project is based on a mature Go client that's been around for over a decade.
|
||||
|
||||
|
||||
## Supported Go Versions
|
||||
|
||||
This client supports two most recent Go release series.
|
||||
|
||||
|
||||
## Supported RabbitMQ Versions
|
||||
|
||||
This project supports RabbitMQ versions starting with `2.0` but primarily tested
|
||||
against [currently supported RabbitMQ release series](https://www.rabbitmq.com/versions.html).
|
||||
|
||||
Some features and behaviours may be server version-specific.
|
||||
|
||||
## Goals
|
||||
|
||||
Provide a functional interface that closely represents the AMQP 0.9.1 model
|
||||
targeted to RabbitMQ as a server. This includes the minimum necessary to
|
||||
interact the semantics of the protocol.
|
||||
|
||||
## Non-goals
|
||||
|
||||
Things not intended to be supported.
|
||||
|
||||
* Auto reconnect and re-synchronization of client and server topologies.
|
||||
* Reconnection would require understanding the error paths when the
|
||||
topology cannot be declared on reconnect. This would require a new set
|
||||
of types and code paths that are best suited at the call-site of this
|
||||
package. AMQP has a dynamic topology that needs all peers to agree. If
|
||||
this doesn't happen, the behavior is undefined. Instead of producing a
|
||||
possible interface with undefined behavior, this package is designed to
|
||||
be simple for the caller to implement the necessary connection-time
|
||||
topology declaration so that reconnection is trivial and encapsulated in
|
||||
the caller's application code.
|
||||
* AMQP Protocol negotiation for forward or backward compatibility.
|
||||
* 0.9.1 is stable and widely deployed. AMQP 1.0 is a divergent
|
||||
specification (a different protocol) and belongs to a different library.
|
||||
* Anything other than PLAIN and EXTERNAL authentication mechanisms.
|
||||
* Keeping the mechanisms interface modular makes it possible to extend
|
||||
outside of this package. If other mechanisms prove to be popular, then
|
||||
we would accept patches to include them in this package.
|
||||
* Support for [`basic.return` and `basic.ack` frame ordering](https://www.rabbitmq.com/confirms.html#when-publishes-are-confirmed).
|
||||
This client uses Go channels for certain protocol events and ordering between
|
||||
events sent to two different channels generally cannot be guaranteed.
|
||||
|
||||
## Usage
|
||||
|
||||
See the [_examples](_examples) subdirectory for simple producers and consumers executables.
|
||||
If you have a use-case in mind which isn't well-represented by the examples,
|
||||
please file an issue.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Godoc API reference](http://godoc.org/github.com/rabbitmq/amqp091-go)
|
||||
* [RabbitMQ tutorials in Go](https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/go)
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are very much welcomed. Create your pull request on a non-main
|
||||
branch, make sure a test or example is included that covers your change, and
|
||||
your commits represent coherent changes that include a reason for the change.
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||
|
||||
## License
|
||||
|
||||
BSD 2 clause, see LICENSE for more details.
|
||||
16
vendor/github.com/rabbitmq/amqp091-go/RELEASE.md
generated
vendored
Normal file
16
vendor/github.com/rabbitmq/amqp091-go/RELEASE.md
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# Guide to release a new version
|
||||
|
||||
1. Update the `buildVersion` constant in [connection.go](https://github.com/rabbitmq/amqp091-go/blob/4886c35d10b273bd374e3ed2356144ad41d27940/connection.go#L31)
|
||||
2. Commit and push. Include the version in the commit message e.g. [this commit](https://github.com/rabbitmq/amqp091-go/commit/52ce2efd03c53dcf77d5496977da46840e9abd24)
|
||||
3. Create a new [GitHub Release](https://github.com/rabbitmq/amqp091-go/releases). Create a new tag as `v<MAJOR>.<MINOR>.<PATCH>`
|
||||
1. Use auto-generate release notes feature in GitHub
|
||||
4. Generate the change log, see [Changelog Generation](#changelog-generation)
|
||||
5. Review the changelog. Watch out for issues closed as "not-fixed" or without a PR
|
||||
6. Commit and Push. Pro-tip: include `[skip ci]` in the commit message to skip the CI run, since it's only documentation
|
||||
7. Send an announcement to the mailing list. Take inspiration from [this message](https://groups.google.com/g/rabbitmq-users/c/EBGYGOWiSgs/m/0sSFuAGICwAJ)
|
||||
|
||||
## Changelog Generation
|
||||
|
||||
```
|
||||
github_changelog_generator --token GITHUB-TOKEN -u rabbitmq -p amqp091-go --no-unreleased --release-branch main
|
||||
```
|
||||
@@ -1,4 +1,9 @@
|
||||
package amqp
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -13,10 +18,10 @@ const (
|
||||
|
||||
// allocator maintains a bitset of allocated numbers.
|
||||
type allocator struct {
|
||||
pool *big.Int
|
||||
last int
|
||||
low int
|
||||
high int
|
||||
pool *big.Int
|
||||
follow int
|
||||
low int
|
||||
high int
|
||||
}
|
||||
|
||||
// NewAllocator reserves and frees integers out of a range between low and
|
||||
@@ -26,10 +31,10 @@ type allocator struct {
|
||||
// sizeof(big.Word)
|
||||
func newAllocator(low, high int) *allocator {
|
||||
return &allocator{
|
||||
pool: big.NewInt(0),
|
||||
last: low,
|
||||
low: low,
|
||||
high: high,
|
||||
pool: big.NewInt(0),
|
||||
follow: low,
|
||||
low: low,
|
||||
high: high,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,21 +69,29 @@ func (a allocator) String() string {
|
||||
// O(N) worst case runtime where N is allocated, but usually O(1) due to a
|
||||
// rolling index into the oldest allocation.
|
||||
func (a *allocator) next() (int, bool) {
|
||||
wrapped := a.last
|
||||
wrapped := a.follow
|
||||
defer func() {
|
||||
// make a.follow point to next value
|
||||
if a.follow == a.high {
|
||||
a.follow = a.low
|
||||
} else {
|
||||
a.follow += 1
|
||||
}
|
||||
}()
|
||||
|
||||
// Find trailing bit
|
||||
for ; a.last <= a.high; a.last++ {
|
||||
if a.reserve(a.last) {
|
||||
return a.last, true
|
||||
for ; a.follow <= a.high; a.follow++ {
|
||||
if a.reserve(a.follow) {
|
||||
return a.follow, true
|
||||
}
|
||||
}
|
||||
|
||||
// Find preceding free'd pool
|
||||
a.last = a.low
|
||||
a.follow = a.low
|
||||
|
||||
for ; a.last < wrapped; a.last++ {
|
||||
if a.reserve(a.last) {
|
||||
return a.last, true
|
||||
for ; a.follow < wrapped; a.follow++ {
|
||||
if a.reserve(a.follow) {
|
||||
return a.follow, true
|
||||
}
|
||||
}
|
||||
|
||||
31
vendor/github.com/streadway/amqp/auth.go → vendor/github.com/rabbitmq/amqp091-go/auth.go
generated
vendored
31
vendor/github.com/streadway/amqp/auth.go → vendor/github.com/rabbitmq/amqp091-go/auth.go
generated
vendored
@@ -1,11 +1,12 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@@ -43,13 +44,33 @@ func (auth *AMQPlainAuth) Mechanism() string {
|
||||
return "AMQPLAIN"
|
||||
}
|
||||
|
||||
// Response returns the null character delimited encoding for the SASL PLAIN Mechanism.
|
||||
// Response returns an AMQP encoded credentials table, without the field table size.
|
||||
func (auth *AMQPlainAuth) Response() string {
|
||||
return fmt.Sprintf("LOGIN:%sPASSWORD:%s", auth.Username, auth.Password)
|
||||
var buf bytes.Buffer
|
||||
table := Table{"LOGIN": auth.Username, "PASSWORD": auth.Password}
|
||||
if err := writeTable(&buf, table); err != nil {
|
||||
return ""
|
||||
}
|
||||
return buf.String()[4:]
|
||||
}
|
||||
|
||||
// ExternalAuth for RabbitMQ-auth-mechanism-ssl.
|
||||
type ExternalAuth struct {
|
||||
}
|
||||
|
||||
// Mechanism returns "EXTERNAL"
|
||||
func (*ExternalAuth) Mechanism() string {
|
||||
return "EXTERNAL"
|
||||
}
|
||||
|
||||
// Response returns an AMQP encoded credentials table, without the field table size.
|
||||
func (*ExternalAuth) Response() string {
|
||||
return "\000*\000*"
|
||||
}
|
||||
|
||||
// Finds the first mechanism preferred by the client that the server supports.
|
||||
func pickSASLMechanism(client []Authentication, serverMechanisms []string) (auth Authentication, ok bool) {
|
||||
|
||||
for _, auth = range client {
|
||||
for _, mech := range serverMechanisms {
|
||||
if auth.Mechanism() == mech {
|
||||
@@ -38,7 +38,7 @@ serial = $dir/serial
|
||||
|
||||
default_crl_days = 7
|
||||
default_days = 3650
|
||||
default_md = sha1
|
||||
default_md = sha256
|
||||
|
||||
policy = testca_policy
|
||||
x509_extensions = certificate_extensions
|
||||
@@ -57,7 +57,7 @@ basicConstraints = CA:false
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = ./private/cakey.pem
|
||||
default_md = sha1
|
||||
default_md = sha256
|
||||
prompt = yes
|
||||
distinguished_name = root_ca_distinguished_name
|
||||
x509_extensions = root_ca_extensions
|
||||
@@ -71,12 +71,12 @@ keyUsage = keyCertSign, cRLSign
|
||||
|
||||
[ client_ca_extensions ]
|
||||
basicConstraints = CA:false
|
||||
keyUsage = digitalSignature
|
||||
keyUsage = keyEncipherment,digitalSignature
|
||||
extendedKeyUsage = 1.3.6.1.5.5.7.3.2
|
||||
|
||||
[ server_ca_extensions ]
|
||||
basicConstraints = CA:false
|
||||
keyUsage = keyEncipherment
|
||||
keyUsage = keyEncipherment,digitalSignature
|
||||
extendedKeyUsage = 1.3.6.1.5.5.7.3.1
|
||||
subjectAltName = @alt_names
|
||||
|
||||
@@ -106,7 +106,7 @@ openssl req \
|
||||
-new \
|
||||
-nodes \
|
||||
-config openssl.cnf \
|
||||
-subj "/CN=127.0.0.1/O=server/" \
|
||||
-subj "/CN=localhost/O=server/" \
|
||||
-key $root/server/key.pem \
|
||||
-out $root/server/req.pem \
|
||||
-outform PEM
|
||||
@@ -115,7 +115,7 @@ openssl req \
|
||||
-new \
|
||||
-nodes \
|
||||
-config openssl.cnf \
|
||||
-subj "/CN=127.0.0.1/O=client/" \
|
||||
-subj "/CN=localhost/O=client/" \
|
||||
-key $root/client/key.pem \
|
||||
-out $root/client/req.pem \
|
||||
-outform PEM
|
||||
4
vendor/github.com/rabbitmq/amqp091-go/change_version.sh
generated
vendored
Normal file
4
vendor/github.com/rabbitmq/amqp091-go/change_version.sh
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
echo $1 > VERSION
|
||||
sed -i -e "s/.*buildVersion = \"*.*/buildVersion = \"$1\"/" ./connection.go
|
||||
go fmt ./...
|
||||
@@ -1,11 +1,12 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -15,14 +16,14 @@ import (
|
||||
// +------+---------+-------------+ +------------+ +-----------+
|
||||
// | type | channel | size | | payload | | frame-end |
|
||||
// +------+---------+-------------+ +------------+ +-----------+
|
||||
// octet short long size octets octet
|
||||
//
|
||||
// octet short long size octets octet
|
||||
const frameHeaderSize = 1 + 2 + 4 + 1
|
||||
|
||||
/*
|
||||
Channel represents an AMQP channel. Used as a context for valid message
|
||||
exchange. Errors on methods with this Channel as a receiver means this channel
|
||||
should be discarded and a new channel established.
|
||||
|
||||
*/
|
||||
type Channel struct {
|
||||
destructor sync.Once
|
||||
@@ -39,6 +40,7 @@ type Channel struct {
|
||||
|
||||
// closed is set to 1 when the channel has been closed - see Channel.send()
|
||||
closed int32
|
||||
close chan struct{}
|
||||
|
||||
// true when we will never notify again
|
||||
noNotify bool
|
||||
@@ -66,7 +68,7 @@ type Channel struct {
|
||||
errors chan *Error
|
||||
|
||||
// State machine that manages frame order, must only be mutated by the connection
|
||||
recv func(*Channel, frame) error
|
||||
recv func(*Channel, frame)
|
||||
|
||||
// Current state for frame re-assembly, only mutated from recv
|
||||
message messageWithContent
|
||||
@@ -84,12 +86,20 @@ func newChannel(c *Connection, id uint16) *Channel {
|
||||
confirms: newConfirms(),
|
||||
recv: (*Channel).recvMethod,
|
||||
errors: make(chan *Error, 1),
|
||||
close: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Signal that from now on, Channel.send() should call Channel.sendClosed()
|
||||
func (ch *Channel) setClosed() {
|
||||
atomic.StoreInt32(&ch.closed, 1)
|
||||
}
|
||||
|
||||
// shutdown is called by Connection after the channel has been removed from the
|
||||
// connection registry.
|
||||
func (ch *Channel) shutdown(e *Error) {
|
||||
ch.setClosed()
|
||||
|
||||
ch.destructor.Do(func() {
|
||||
ch.m.Lock()
|
||||
defer ch.m.Unlock()
|
||||
@@ -103,14 +113,7 @@ func (ch *Channel) shutdown(e *Error) {
|
||||
for _, c := range ch.closes {
|
||||
c <- e
|
||||
}
|
||||
}
|
||||
|
||||
// Signal that from now on, Channel.send() should call
|
||||
// Channel.sendClosed()
|
||||
atomic.StoreInt32(&ch.closed, 1)
|
||||
|
||||
// Notify RPC if we're selecting
|
||||
if e != nil {
|
||||
// Notify RPC if we're selecting
|
||||
ch.errors <- e
|
||||
}
|
||||
|
||||
@@ -144,6 +147,7 @@ func (ch *Channel) shutdown(e *Error) {
|
||||
}
|
||||
|
||||
close(ch.errors)
|
||||
close(ch.close)
|
||||
ch.noNotify = true
|
||||
})
|
||||
}
|
||||
@@ -154,7 +158,7 @@ func (ch *Channel) shutdown(e *Error) {
|
||||
// only 'channel.close' is sent to the server.
|
||||
func (ch *Channel) send(msg message) (err error) {
|
||||
// If the channel is closed, use Channel.sendClosed()
|
||||
if atomic.LoadInt32(&ch.closed) == 1 {
|
||||
if ch.IsClosed() {
|
||||
return ch.sendClosed(msg)
|
||||
}
|
||||
|
||||
@@ -230,14 +234,38 @@ func (ch *Channel) sendOpen(msg message) (err error) {
|
||||
size = len(body)
|
||||
}
|
||||
|
||||
if err = ch.connection.send(&methodFrame{
|
||||
// If the channel is closed, use Channel.sendClosed()
|
||||
if ch.IsClosed() {
|
||||
return ch.sendClosed(msg)
|
||||
}
|
||||
|
||||
// Flush the buffer only after all the Frames that comprise the Message
|
||||
// have been written to maximise benefits of using a buffered writer.
|
||||
defer func() {
|
||||
if endError := ch.connection.endSendUnflushed(); endError != nil {
|
||||
if err == nil {
|
||||
err = endError
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// We use sendUnflushed() in this method as sending the message requires
|
||||
// sending multiple Frames (methodFrame, headerFrame, N x bodyFrame).
|
||||
// Flushing after each Frame is inefficient, as it negates much of the
|
||||
// benefit of using a buffered writer and results in more syscalls than
|
||||
// necessary. Flushing buffers after every frame can have a significant
|
||||
// performance impact when sending (e.g. basicPublish) small messages,
|
||||
// so sendUnflushed() performs an *Unflushed* write, but is otherwise
|
||||
// equivalent to the send() method. We later use the separate flush
|
||||
// method to explicitly flush the buffer after all Frames are written.
|
||||
if err = ch.connection.sendUnflushed(&methodFrame{
|
||||
ChannelId: ch.id,
|
||||
Method: content,
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = ch.connection.send(&headerFrame{
|
||||
if err = ch.connection.sendUnflushed(&headerFrame{
|
||||
ChannelId: ch.id,
|
||||
ClassId: class,
|
||||
Size: uint64(len(body)),
|
||||
@@ -252,7 +280,7 @@ func (ch *Channel) sendOpen(msg message) (err error) {
|
||||
j = len(body)
|
||||
}
|
||||
|
||||
if err = ch.connection.send(&bodyFrame{
|
||||
if err = ch.connection.sendUnflushed(&bodyFrame{
|
||||
ChannelId: ch.id,
|
||||
Body: body[i:j],
|
||||
}); err != nil {
|
||||
@@ -260,6 +288,11 @@ func (ch *Channel) sendOpen(msg message) (err error) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If the channel is closed, use Channel.sendClosed()
|
||||
if ch.IsClosed() {
|
||||
return ch.sendClosed(msg)
|
||||
}
|
||||
|
||||
err = ch.connection.send(&methodFrame{
|
||||
ChannelId: ch.id,
|
||||
Method: msg,
|
||||
@@ -274,11 +307,16 @@ func (ch *Channel) sendOpen(msg message) (err error) {
|
||||
func (ch *Channel) dispatch(msg message) {
|
||||
switch m := msg.(type) {
|
||||
case *channelClose:
|
||||
// Note: channel state is set to closed immedately after the message is
|
||||
// decoded by the Connection
|
||||
|
||||
// lock before sending connection.close-ok
|
||||
// to avoid unexpected interleaving with basic.publish frames if
|
||||
// publishing is happening concurrently
|
||||
ch.m.Lock()
|
||||
ch.send(&channelCloseOk{})
|
||||
if err := ch.send(&channelCloseOk{}); err != nil {
|
||||
Logger.Printf("error sending channelCloseOk, channel id: %d error: %+v", ch.id, err)
|
||||
}
|
||||
ch.m.Unlock()
|
||||
ch.connection.closeChannel(ch, newError(m.ReplyCode, m.ReplyText))
|
||||
|
||||
@@ -288,7 +326,9 @@ func (ch *Channel) dispatch(msg message) {
|
||||
c <- m.Active
|
||||
}
|
||||
ch.notifyM.RUnlock()
|
||||
ch.send(&channelFlowOk{Active: m.Active})
|
||||
if err := ch.send(&channelFlowOk{Active: m.Active}); err != nil {
|
||||
Logger.Printf("error sending channelFlowOk, channel id: %d error: %+v", ch.id, err)
|
||||
}
|
||||
|
||||
case *basicCancel:
|
||||
ch.notifyM.RLock()
|
||||
@@ -330,44 +370,49 @@ func (ch *Channel) dispatch(msg message) {
|
||||
// deliveries are in flight and a no-wait cancel has happened
|
||||
|
||||
default:
|
||||
ch.rpc <- msg
|
||||
select {
|
||||
case <-ch.close:
|
||||
return
|
||||
case ch.rpc <- msg:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ch *Channel) transition(f func(*Channel, frame) error) error {
|
||||
func (ch *Channel) transition(f func(*Channel, frame)) {
|
||||
ch.recv = f
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ch *Channel) recvMethod(f frame) error {
|
||||
func (ch *Channel) recvMethod(f frame) {
|
||||
switch frame := f.(type) {
|
||||
case *methodFrame:
|
||||
if msg, ok := frame.Method.(messageWithContent); ok {
|
||||
ch.body = make([]byte, 0)
|
||||
ch.message = msg
|
||||
return ch.transition((*Channel).recvHeader)
|
||||
ch.transition((*Channel).recvHeader)
|
||||
return
|
||||
}
|
||||
|
||||
ch.dispatch(frame.Method) // termination state
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
ch.transition((*Channel).recvMethod)
|
||||
|
||||
case *headerFrame:
|
||||
// drop
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
ch.transition((*Channel).recvMethod)
|
||||
|
||||
case *bodyFrame:
|
||||
// drop
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
}
|
||||
ch.transition((*Channel).recvMethod)
|
||||
|
||||
panic("unexpected frame type")
|
||||
default:
|
||||
panic("unexpected frame type")
|
||||
}
|
||||
}
|
||||
|
||||
func (ch *Channel) recvHeader(f frame) error {
|
||||
func (ch *Channel) recvHeader(f frame) {
|
||||
switch frame := f.(type) {
|
||||
case *methodFrame:
|
||||
// interrupt content and handle method
|
||||
return ch.recvMethod(f)
|
||||
ch.recvMethod(f)
|
||||
|
||||
case *headerFrame:
|
||||
// start collecting if we expect body frames
|
||||
@@ -376,29 +421,31 @@ func (ch *Channel) recvHeader(f frame) error {
|
||||
if frame.Size == 0 {
|
||||
ch.message.setContent(ch.header.Properties, ch.body)
|
||||
ch.dispatch(ch.message) // termination state
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
ch.transition((*Channel).recvMethod)
|
||||
return
|
||||
}
|
||||
return ch.transition((*Channel).recvContent)
|
||||
ch.transition((*Channel).recvContent)
|
||||
|
||||
case *bodyFrame:
|
||||
// drop and reset
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
}
|
||||
ch.transition((*Channel).recvMethod)
|
||||
|
||||
panic("unexpected frame type")
|
||||
default:
|
||||
panic("unexpected frame type")
|
||||
}
|
||||
}
|
||||
|
||||
// state after method + header and before the length
|
||||
// defined by the header has been reached
|
||||
func (ch *Channel) recvContent(f frame) error {
|
||||
func (ch *Channel) recvContent(f frame) {
|
||||
switch frame := f.(type) {
|
||||
case *methodFrame:
|
||||
// interrupt content and handle method
|
||||
return ch.recvMethod(f)
|
||||
ch.recvMethod(f)
|
||||
|
||||
case *headerFrame:
|
||||
// drop and reset
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
ch.transition((*Channel).recvMethod)
|
||||
|
||||
case *bodyFrame:
|
||||
if cap(ch.body) == 0 {
|
||||
@@ -409,13 +456,15 @@ func (ch *Channel) recvContent(f frame) error {
|
||||
if uint64(len(ch.body)) >= ch.header.Size {
|
||||
ch.message.setContent(ch.header.Properties, ch.body)
|
||||
ch.dispatch(ch.message) // termination state
|
||||
return ch.transition((*Channel).recvMethod)
|
||||
ch.transition((*Channel).recvMethod)
|
||||
return
|
||||
}
|
||||
|
||||
return ch.transition((*Channel).recvContent)
|
||||
}
|
||||
ch.transition((*Channel).recvContent)
|
||||
|
||||
panic("unexpected frame type")
|
||||
default:
|
||||
panic("unexpected frame type")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -423,9 +472,12 @@ Close initiate a clean channel closure by sending a close message with the error
|
||||
code set to '200'.
|
||||
|
||||
It is safe to call this method multiple times.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Close() error {
|
||||
if ch.IsClosed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer ch.connection.closeChannel(ch, nil)
|
||||
return ch.call(
|
||||
&channelClose{ReplyCode: replySuccess},
|
||||
@@ -433,6 +485,12 @@ func (ch *Channel) Close() error {
|
||||
)
|
||||
}
|
||||
|
||||
// IsClosed returns true if the channel is marked as closed, otherwise false
|
||||
// is returned.
|
||||
func (ch *Channel) IsClosed() bool {
|
||||
return atomic.LoadInt32(&ch.closed) == 1
|
||||
}
|
||||
|
||||
/*
|
||||
NotifyClose registers a listener for when the server sends a channel or
|
||||
connection exception in the form of a Connection.Close or Channel.Close method.
|
||||
@@ -443,6 +501,8 @@ this channel.
|
||||
The chan provided will be closed when the Channel is closed and on a
|
||||
graceful close, no error will be sent.
|
||||
|
||||
In case of a non graceful close the error will be notified synchronously by the library
|
||||
so that it will be necessary to consume the Channel from the caller in order to avoid deadlocks
|
||||
*/
|
||||
func (ch *Channel) NotifyClose(c chan *Error) chan *Error {
|
||||
ch.notifyM.Lock()
|
||||
@@ -488,7 +548,6 @@ much on the same connection, all channels using that connection will suffer,
|
||||
including acknowledgments from deliveries. Use different Connections if you
|
||||
desire to interleave consumers and producers in the same process to avoid your
|
||||
basic.ack messages from getting rate limited with your basic.publish messages.
|
||||
|
||||
*/
|
||||
func (ch *Channel) NotifyFlow(c chan bool) chan bool {
|
||||
ch.notifyM.Lock()
|
||||
@@ -510,7 +569,6 @@ immediate flags.
|
||||
|
||||
A return struct has a copy of the Publishing along with some error
|
||||
information about why the publishing failed.
|
||||
|
||||
*/
|
||||
func (ch *Channel) NotifyReturn(c chan Return) chan Return {
|
||||
ch.notifyM.Lock()
|
||||
@@ -531,7 +589,6 @@ from the server when a queue is deleted or when consuming from a mirrored queue
|
||||
where the master has just failed (and was moved to another node).
|
||||
|
||||
The subscription tag is returned to the listener.
|
||||
|
||||
*/
|
||||
func (ch *Channel) NotifyCancel(c chan string) chan string {
|
||||
ch.notifyM.Lock()
|
||||
@@ -594,6 +651,8 @@ or Channel while confirms are in-flight.
|
||||
It's advisable to wait for all Confirmations to arrive before calling
|
||||
Channel.Close() or Connection.Close().
|
||||
|
||||
It is also advisable for the caller to consume from the channel returned till it is closed
|
||||
to avoid possible deadlocks
|
||||
*/
|
||||
func (ch *Channel) NotifyPublish(confirm chan Confirmation) chan Confirmation {
|
||||
ch.notifyM.Lock()
|
||||
@@ -606,7 +665,6 @@ func (ch *Channel) NotifyPublish(confirm chan Confirmation) chan Confirmation {
|
||||
}
|
||||
|
||||
return confirm
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -672,7 +730,6 @@ When noWait is true, do not wait for the server to acknowledge the cancel.
|
||||
Only use this when you are certain there are no deliveries in flight that
|
||||
require an acknowledgment, otherwise they will arrive and be dropped in the
|
||||
client without an ack, and will not be redelivered to other consumers.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Cancel(consumer string, noWait bool) error {
|
||||
req := &basicCancel{
|
||||
@@ -705,12 +762,12 @@ the type "direct" with the routing key matching the queue's name. With this
|
||||
default binding, it is possible to publish messages that route directly to
|
||||
this queue by publishing to "" with the routing key of the queue name.
|
||||
|
||||
QueueDeclare("alerts", true, false, false, false, nil)
|
||||
Publish("", "alerts", false, false, Publishing{Body: []byte("...")})
|
||||
QueueDeclare("alerts", true, false, false, false, nil)
|
||||
Publish("", "alerts", false, false, Publishing{Body: []byte("...")})
|
||||
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alerts -> "" -> alerts -> alerts
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alerts -> "" -> alerts -> alerts
|
||||
|
||||
The queue name may be empty, in which case the server will generate a unique name
|
||||
which will be returned in the Name field of Queue struct.
|
||||
@@ -746,7 +803,6 @@ or attempting to modify an existing queue from a different connection.
|
||||
|
||||
When the error return value is not nil, you can assume the queue could not be
|
||||
declared with these parameters, and the channel will be closed.
|
||||
|
||||
*/
|
||||
func (ch *Channel) QueueDeclare(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error) {
|
||||
if err := args.Validate(); err != nil {
|
||||
@@ -780,13 +836,11 @@ func (ch *Channel) QueueDeclare(name string, durable, autoDelete, exclusive, noW
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
QueueDeclarePassive is functionally and parametrically equivalent to
|
||||
QueueDeclare, except that it sets the "passive" attribute to true. A passive
|
||||
queue is assumed by RabbitMQ to already exist, and attempting to connect to a
|
||||
non-existent queue will cause RabbitMQ to throw an exception. This function
|
||||
can be used to test for the existence of a queue.
|
||||
|
||||
*/
|
||||
func (ch *Channel) QueueDeclarePassive(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error) {
|
||||
if err := args.Validate(); err != nil {
|
||||
@@ -833,6 +887,7 @@ declared with specific parameters.
|
||||
If a queue by this name does not exist, an error will be returned and the
|
||||
channel will be closed.
|
||||
|
||||
Deprecated: Use QueueDeclare with "Passive: true" instead.
|
||||
*/
|
||||
func (ch *Channel) QueueInspect(name string) (Queue, error) {
|
||||
req := &queueDeclare{
|
||||
@@ -857,14 +912,14 @@ QueueBind binds an exchange to a queue so that publishings to the exchange will
|
||||
be routed to the queue when the publishing routing key matches the binding
|
||||
routing key.
|
||||
|
||||
QueueBind("pagers", "alert", "log", false, nil)
|
||||
QueueBind("emails", "info", "log", false, nil)
|
||||
QueueBind("pagers", "alert", "log", false, nil)
|
||||
QueueBind("emails", "info", "log", false, nil)
|
||||
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alert --> log ----> alert --> pagers
|
||||
key: info ---> log ----> info ---> emails
|
||||
key: debug --> log (none) (dropped)
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alert --> log ----> alert --> pagers
|
||||
key: info ---> log ----> info ---> emails
|
||||
key: debug --> log (none) (dropped)
|
||||
|
||||
If a binding with the same key and arguments already exists between the
|
||||
exchange and queue, the attempt to rebind will be ignored and the existing
|
||||
@@ -874,16 +929,16 @@ In the case that multiple bindings may cause the message to be routed to the
|
||||
same queue, the server will only route the publishing once. This is possible
|
||||
with topic exchanges.
|
||||
|
||||
QueueBind("pagers", "alert", "amq.topic", false, nil)
|
||||
QueueBind("emails", "info", "amq.topic", false, nil)
|
||||
QueueBind("emails", "#", "amq.topic", false, nil) // match everything
|
||||
QueueBind("pagers", "alert", "amq.topic", false, nil)
|
||||
QueueBind("emails", "info", "amq.topic", false, nil)
|
||||
QueueBind("emails", "#", "amq.topic", false, nil) // match everything
|
||||
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alert --> amq.topic ----> alert --> pagers
|
||||
key: info ---> amq.topic ----> # ------> emails
|
||||
\---> info ---/
|
||||
key: debug --> amq.topic ----> # ------> emails
|
||||
Delivery Exchange Key Queue
|
||||
-----------------------------------------------
|
||||
key: alert --> amq.topic ----> alert --> pagers
|
||||
key: info ---> amq.topic ----> # ------> emails
|
||||
\---> info ---/
|
||||
key: debug --> amq.topic ----> # ------> emails
|
||||
|
||||
It is only possible to bind a durable queue to a durable exchange regardless of
|
||||
whether the queue or exchange is auto-deleted. Bindings between durable queues
|
||||
@@ -894,7 +949,6 @@ will be closed.
|
||||
|
||||
When noWait is false and the queue could not be bound, the channel will be
|
||||
closed with an error.
|
||||
|
||||
*/
|
||||
func (ch *Channel) QueueBind(name, key, exchange string, noWait bool, args Table) error {
|
||||
if err := args.Validate(); err != nil {
|
||||
@@ -916,10 +970,6 @@ func (ch *Channel) QueueBind(name, key, exchange string, noWait bool, args Table
|
||||
/*
|
||||
QueueUnbind removes a binding between an exchange and queue matching the key and
|
||||
arguments.
|
||||
|
||||
It is possible to send and empty string for the exchange name which means to
|
||||
unbind the queue from the default exchange.
|
||||
|
||||
*/
|
||||
func (ch *Channel) QueueUnbind(name, key, exchange string, args Table) error {
|
||||
if err := args.Validate(); err != nil {
|
||||
@@ -976,7 +1026,6 @@ When noWait is true, the queue will be deleted without waiting for a response
|
||||
from the server. The purged message count will not be meaningful. If the queue
|
||||
could not be deleted, a channel exception will be raised and the channel will
|
||||
be closed.
|
||||
|
||||
*/
|
||||
func (ch *Channel) QueueDelete(name string, ifUnused, ifEmpty, noWait bool) (int, error) {
|
||||
req := &queueDelete{
|
||||
@@ -1043,11 +1092,11 @@ Inflight messages, limited by Channel.Qos will be buffered until received from
|
||||
the returned chan.
|
||||
|
||||
When the Channel or Connection is closed, all buffered and inflight messages will
|
||||
be dropped.
|
||||
be dropped. RabbitMQ will requeue messages not acknowledged. In other words, dropped
|
||||
messages in this way won't be lost.
|
||||
|
||||
When the consumer tag is cancelled, all inflight messages will be delivered until
|
||||
the returned chan is closed.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Consume(queue, consumer string, autoAck, exclusive, noLocal, noWait bool, args Table) (<-chan Delivery, error) {
|
||||
// When we return from ch.call, there may be a delivery already for the
|
||||
@@ -1082,7 +1131,122 @@ func (ch *Channel) Consume(queue, consumer string, autoAck, exclusive, noLocal,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return (<-chan Delivery)(deliveries), nil
|
||||
return deliveries, nil
|
||||
}
|
||||
|
||||
/*
|
||||
ConsumeWithContext immediately starts delivering queued messages.
|
||||
|
||||
This function is similar to Channel.Consume, and accepts a context to control
|
||||
consumer lifecycle. When the context passed to this function is canceled, the
|
||||
consumer associated with the deliveries channel will be canceled too. When the
|
||||
context passed to this function is cancelled, the deliveries channel will be closed.
|
||||
|
||||
An application is advised to keep on receiving messages from the delivery channel
|
||||
until the channel is empty. This is specially important to avoid memory leaks from
|
||||
unconsumed messages from the delivery channel.
|
||||
|
||||
Begin receiving on the returned chan Delivery before any other operation on the
|
||||
Connection or Channel.
|
||||
|
||||
Continues deliveries to the returned chan Delivery until Channel.Cancel,
|
||||
Connection.Close, Channel.Close, context is cancelled, or an AMQP exception
|
||||
occurs. Consumers must range over the chan to ensure all deliveries are
|
||||
received. Unreceived deliveries will block all methods on the same connection.
|
||||
|
||||
All deliveries in AMQP must be acknowledged. It is expected of the consumer to
|
||||
call Delivery.Ack after it has successfully processed the delivery. If the
|
||||
consumer is cancelled or the channel or connection is closed any unacknowledged
|
||||
deliveries will be requeued at the end of the same queue.
|
||||
|
||||
The consumer is identified by a string that is unique and scoped for all
|
||||
consumers on this channel. If you wish to eventually cancel the consumer, use
|
||||
the same non-empty identifier in Channel.Cancel. An empty string will cause
|
||||
the library to generate a unique identity. The consumer identity will be
|
||||
included in every Delivery in the ConsumerTag field
|
||||
|
||||
When autoAck (also known as noAck) is true, the server will acknowledge
|
||||
deliveries to this consumer prior to writing the delivery to the network. When
|
||||
autoAck is true, the consumer should not call Delivery.Ack. Automatically
|
||||
acknowledging deliveries means that some deliveries may get lost if the
|
||||
consumer is unable to process them after the server delivers them.
|
||||
See http://www.rabbitmq.com/confirms.html for more details.
|
||||
|
||||
When exclusive is true, the server will ensure that this is the sole consumer
|
||||
from this queue. When exclusive is false, the server will fairly distribute
|
||||
deliveries across multiple consumers.
|
||||
|
||||
The noLocal flag is not supported by RabbitMQ.
|
||||
|
||||
It's advisable to use separate connections for Channel.Publish and
|
||||
Channel.Consume so not to have TCP pushback on publishing affect the ability to
|
||||
consume messages, so this parameter is here mostly for completeness.
|
||||
|
||||
When noWait is true, do not wait for the server to confirm the request and
|
||||
immediately begin deliveries. If it is not possible to consume, a channel
|
||||
exception will be raised and the channel will be closed.
|
||||
|
||||
Optional arguments can be provided that have specific semantics for the queue
|
||||
or server.
|
||||
|
||||
Inflight messages, limited by Channel.Qos will be buffered until received from
|
||||
the returned chan.
|
||||
|
||||
When the Channel or Connection is closed, all buffered and inflight messages will
|
||||
be dropped. RabbitMQ will requeue messages not acknowledged. In other words, dropped
|
||||
messages in this way won't be lost.
|
||||
*/
|
||||
func (ch *Channel) ConsumeWithContext(ctx context.Context, queue, consumer string, autoAck, exclusive, noLocal, noWait bool, args Table) (<-chan Delivery, error) {
|
||||
// When we return from ch.call, there may be a delivery already for the
|
||||
// consumer that hasn't been added to the consumer hash yet. Because of
|
||||
// this, we never rely on the server picking a consumer tag for us.
|
||||
|
||||
if err := args.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if consumer == "" {
|
||||
consumer = uniqueConsumerTag()
|
||||
}
|
||||
|
||||
req := &basicConsume{
|
||||
Queue: queue,
|
||||
ConsumerTag: consumer,
|
||||
NoLocal: noLocal,
|
||||
NoAck: autoAck,
|
||||
Exclusive: exclusive,
|
||||
NoWait: noWait,
|
||||
Arguments: args,
|
||||
}
|
||||
res := &basicConsumeOk{}
|
||||
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
deliveries := make(chan Delivery)
|
||||
|
||||
ch.consumers.add(consumer, deliveries)
|
||||
|
||||
if err := ch.call(req, res); err != nil {
|
||||
ch.consumers.cancel(consumer)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
select {
|
||||
case <-ch.consumers.closed:
|
||||
return
|
||||
case <-ctx.Done():
|
||||
if ch != nil {
|
||||
_ = ch.Cancel(consumer, false)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return deliveries, nil
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1126,7 +1290,7 @@ Note: RabbitMQ declares the default exchange types like 'amq.fanout' as
|
||||
durable, so queues that bind to these pre-declared exchanges must also be
|
||||
durable.
|
||||
|
||||
Exchanges declared as `internal` do not accept accept publishings. Internal
|
||||
Exchanges declared as `internal` do not accept publishings. Internal
|
||||
exchanges are useful when you wish to implement inter-exchange topologies
|
||||
that should not be exposed to users of the broker.
|
||||
|
||||
@@ -1158,13 +1322,11 @@ func (ch *Channel) ExchangeDeclare(name, kind string, durable, autoDelete, inter
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
ExchangeDeclarePassive is functionally and parametrically equivalent to
|
||||
ExchangeDeclare, except that it sets the "passive" attribute to true. A passive
|
||||
exchange is assumed by RabbitMQ to already exist, and attempting to connect to a
|
||||
non-existent exchange will cause RabbitMQ to throw an exception. This function
|
||||
can be used to detect the existence of an exchange.
|
||||
|
||||
*/
|
||||
func (ch *Channel) ExchangeDeclarePassive(name, kind string, durable, autoDelete, internal, noWait bool, args Table) error {
|
||||
if err := args.Validate(); err != nil {
|
||||
@@ -1227,14 +1389,14 @@ exchange even though multiple bindings will match.
|
||||
Given a message delivered to the source exchange, the message will be forwarded
|
||||
to the destination exchange when the routing key is matched.
|
||||
|
||||
ExchangeBind("sell", "MSFT", "trade", false, nil)
|
||||
ExchangeBind("buy", "AAPL", "trade", false, nil)
|
||||
ExchangeBind("sell", "MSFT", "trade", false, nil)
|
||||
ExchangeBind("buy", "AAPL", "trade", false, nil)
|
||||
|
||||
Delivery Source Key Destination
|
||||
example exchange exchange
|
||||
-----------------------------------------------
|
||||
key: AAPL --> trade ----> MSFT sell
|
||||
\---> AAPL --> buy
|
||||
Delivery Source Key Destination
|
||||
example exchange exchange
|
||||
-----------------------------------------------
|
||||
key: AAPL --> trade ----> MSFT sell
|
||||
\---> AAPL --> buy
|
||||
|
||||
When noWait is true, do not wait for the server to confirm the binding. If any
|
||||
error occurs the channel will be closed. Add a listener to NotifyClose to
|
||||
@@ -1321,16 +1483,69 @@ confirmations start at 1. Exit when all publishings are confirmed.
|
||||
|
||||
When Publish does not return an error and the channel is in confirm mode, the
|
||||
internal counter for DeliveryTags with the first confirmation starts at 1.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Publish(exchange, key string, mandatory, immediate bool, msg Publishing) error {
|
||||
_, err := ch.PublishWithDeferredConfirm(exchange, key, mandatory, immediate, msg)
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
PublishWithContext sends a Publishing from the client to an exchange on the server.
|
||||
|
||||
NOTE: this function is equivalent to [Channel.Publish]. Context is not honoured.
|
||||
|
||||
When you want a single message to be delivered to a single queue, you can
|
||||
publish to the default exchange with the routingKey of the queue name. This is
|
||||
because every declared queue gets an implicit route to the default exchange.
|
||||
|
||||
Since publishings are asynchronous, any undeliverable message will get returned
|
||||
by the server. Add a listener with Channel.NotifyReturn to handle any
|
||||
undeliverable message when calling publish with either the mandatory or
|
||||
immediate parameters as true.
|
||||
|
||||
Publishings can be undeliverable when the mandatory flag is true and no queue is
|
||||
bound that matches the routing key, or when the immediate flag is true and no
|
||||
consumer on the matched queue is ready to accept the delivery.
|
||||
|
||||
This can return an error when the channel, connection or socket is closed. The
|
||||
error or lack of an error does not indicate whether the server has received this
|
||||
publishing.
|
||||
|
||||
It is possible for publishing to not reach the broker if the underlying socket
|
||||
is shut down without pending publishing packets being flushed from the kernel
|
||||
buffers. The easy way of making it probable that all publishings reach the
|
||||
server is to always call Connection.Close before terminating your publishing
|
||||
application. The way to ensure that all publishings reach the server is to add
|
||||
a listener to Channel.NotifyPublish and put the channel in confirm mode with
|
||||
Channel.Confirm. Publishing delivery tags and their corresponding
|
||||
confirmations start at 1. Exit when all publishings are confirmed.
|
||||
|
||||
When Publish does not return an error and the channel is in confirm mode, the
|
||||
internal counter for DeliveryTags with the first confirmation starts at 1.
|
||||
*/
|
||||
func (ch *Channel) PublishWithContext(_ context.Context, exchange, key string, mandatory, immediate bool, msg Publishing) error {
|
||||
return ch.Publish(exchange, key, mandatory, immediate, msg)
|
||||
}
|
||||
|
||||
/*
|
||||
PublishWithDeferredConfirm behaves identically to Publish, but additionally
|
||||
returns a DeferredConfirmation, allowing the caller to wait on the publisher
|
||||
confirmation for this message. If the channel has not been put into confirm
|
||||
mode, the DeferredConfirmation will be nil.
|
||||
*/
|
||||
func (ch *Channel) PublishWithDeferredConfirm(exchange, key string, mandatory, immediate bool, msg Publishing) (*DeferredConfirmation, error) {
|
||||
if err := msg.Headers.Validate(); err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch.m.Lock()
|
||||
defer ch.m.Unlock()
|
||||
|
||||
var dc *DeferredConfirmation
|
||||
if ch.confirming {
|
||||
dc = ch.confirms.publish()
|
||||
}
|
||||
|
||||
if err := ch.send(&basicPublish{
|
||||
Exchange: exchange,
|
||||
RoutingKey: key,
|
||||
@@ -1353,14 +1568,26 @@ func (ch *Channel) Publish(exchange, key string, mandatory, immediate bool, msg
|
||||
AppId: msg.AppId,
|
||||
},
|
||||
}); err != nil {
|
||||
return err
|
||||
if ch.confirming {
|
||||
ch.confirms.unpublish()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ch.confirming {
|
||||
ch.confirms.Publish()
|
||||
}
|
||||
return dc, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
/*
|
||||
PublishWithDeferredConfirmWithContext behaves identically to Publish but additionally returns a
|
||||
DeferredConfirmation, allowing the caller to wait on the publisher confirmation
|
||||
for this message. If the channel has not been put into confirm mode,
|
||||
the DeferredConfirmation will be nil.
|
||||
|
||||
NOTE: PublishWithDeferredConfirmWithContext is equivalent to its non-context variant. The context passed
|
||||
to this function is not honoured.
|
||||
*/
|
||||
func (ch *Channel) PublishWithDeferredConfirmWithContext(_ context.Context, exchange, key string, mandatory, immediate bool, msg Publishing) (*DeferredConfirmation, error) {
|
||||
return ch.PublishWithDeferredConfirm(exchange, key, mandatory, immediate, msg)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1379,7 +1606,6 @@ delivery.
|
||||
When autoAck is true, the server will automatically acknowledge this message so
|
||||
you don't have to. But if you are unable to fully process this message before
|
||||
the channel or connection is closed, the message will not get requeued.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Get(queue string, autoAck bool) (msg Delivery, ok bool, err error) {
|
||||
req := &basicGet{Queue: queue, NoAck: autoAck}
|
||||
@@ -1411,7 +1637,6 @@ the channel is in a transaction is not defined.
|
||||
|
||||
Once a channel has been put into transaction mode, it cannot be taken out of
|
||||
transaction mode. Use a different channel for non-transactional semantics.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Tx() error {
|
||||
return ch.call(
|
||||
@@ -1425,7 +1650,6 @@ TxCommit atomically commits all publishings and acknowledgments for a single
|
||||
queue and immediately start a new transaction.
|
||||
|
||||
Calling this method without having called Channel.Tx is an error.
|
||||
|
||||
*/
|
||||
func (ch *Channel) TxCommit() error {
|
||||
return ch.call(
|
||||
@@ -1439,7 +1663,6 @@ TxRollback atomically rolls back all publishings and acknowledgments for a
|
||||
single queue and immediately start a new transaction.
|
||||
|
||||
Calling this method without having called Channel.Tx is an error.
|
||||
|
||||
*/
|
||||
func (ch *Channel) TxRollback() error {
|
||||
return ch.call(
|
||||
@@ -1469,7 +1692,6 @@ pause its publishings when `false` is sent on that channel.
|
||||
Note: RabbitMQ prefers to use TCP push back to control flow for all channels on
|
||||
a connection, so under high volume scenarios, it's wise to open separate
|
||||
Connections for publishings and deliveries.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Flow(active bool) error {
|
||||
return ch.call(
|
||||
@@ -1501,7 +1723,6 @@ persisting the message if necessary.
|
||||
|
||||
When noWait is true, the client will not wait for a response. A channel
|
||||
exception could occur if the server does not support this method.
|
||||
|
||||
*/
|
||||
func (ch *Channel) Confirm(noWait bool) error {
|
||||
if err := ch.call(
|
||||
@@ -1530,6 +1751,11 @@ If the deliveries cannot be recovered, an error will be returned and the channel
|
||||
will be closed.
|
||||
|
||||
Note: this method is not implemented on RabbitMQ, use Delivery.Nack instead
|
||||
|
||||
Deprecated: This method is deprecated in RabbitMQ. RabbitMQ used Recover(true)
|
||||
as a mechanism for consumers to tell the broker that they were ready for more
|
||||
deliveries, back in 2008-2009. Support for this will be removed from RabbitMQ in
|
||||
a future release. Use Nack() with requeue=true instead.
|
||||
*/
|
||||
func (ch *Channel) Recover(requeue bool) error {
|
||||
return ch.call(
|
||||
@@ -1591,3 +1817,12 @@ func (ch *Channel) Reject(tag uint64, requeue bool) error {
|
||||
Requeue: requeue,
|
||||
})
|
||||
}
|
||||
|
||||
// GetNextPublishSeqNo returns the sequence number of the next message to be
|
||||
// published, when in confirm mode.
|
||||
func (ch *Channel) GetNextPublishSeqNo() uint64 {
|
||||
ch.confirms.publishedMut.Lock()
|
||||
defer ch.confirms.publishedMut.Unlock()
|
||||
|
||||
return ch.confirms.published + 1
|
||||
}
|
||||
238
vendor/github.com/rabbitmq/amqp091-go/confirms.go
generated
vendored
Normal file
238
vendor/github.com/rabbitmq/amqp091-go/confirms.go
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// confirms resequences and notifies one or multiple publisher confirmation listeners
|
||||
type confirms struct {
|
||||
m sync.Mutex
|
||||
listeners []chan Confirmation
|
||||
sequencer map[uint64]Confirmation
|
||||
deferredConfirmations *deferredConfirmations
|
||||
published uint64
|
||||
publishedMut sync.Mutex
|
||||
expecting uint64
|
||||
}
|
||||
|
||||
// newConfirms allocates a confirms
|
||||
func newConfirms() *confirms {
|
||||
return &confirms{
|
||||
sequencer: map[uint64]Confirmation{},
|
||||
deferredConfirmations: newDeferredConfirmations(),
|
||||
published: 0,
|
||||
expecting: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *confirms) Listen(l chan Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.listeners = append(c.listeners, l)
|
||||
}
|
||||
|
||||
// Publish increments the publishing counter
|
||||
func (c *confirms) publish() *DeferredConfirmation {
|
||||
c.publishedMut.Lock()
|
||||
defer c.publishedMut.Unlock()
|
||||
|
||||
c.published++
|
||||
return c.deferredConfirmations.Add(c.published)
|
||||
}
|
||||
|
||||
// unpublish decrements the publishing counter and removes the
|
||||
// DeferredConfirmation. It must be called immediately after a publish fails.
|
||||
func (c *confirms) unpublish() {
|
||||
c.publishedMut.Lock()
|
||||
defer c.publishedMut.Unlock()
|
||||
c.deferredConfirmations.remove(c.published)
|
||||
c.published--
|
||||
}
|
||||
|
||||
// confirm confirms one publishing, increments the expecting delivery tag, and
|
||||
// removes bookkeeping for that delivery tag.
|
||||
func (c *confirms) confirm(confirmation Confirmation) {
|
||||
delete(c.sequencer, c.expecting)
|
||||
c.expecting++
|
||||
for _, l := range c.listeners {
|
||||
l <- confirmation
|
||||
}
|
||||
}
|
||||
|
||||
// resequence confirms any out of order delivered confirmations
|
||||
func (c *confirms) resequence() {
|
||||
c.publishedMut.Lock()
|
||||
defer c.publishedMut.Unlock()
|
||||
|
||||
for c.expecting <= c.published {
|
||||
sequenced, found := c.sequencer[c.expecting]
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
c.confirm(sequenced)
|
||||
}
|
||||
}
|
||||
|
||||
// One confirms one publishing and all following in the publishing sequence
|
||||
func (c *confirms) One(confirmed Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.deferredConfirmations.Confirm(confirmed)
|
||||
|
||||
if c.expecting == confirmed.DeliveryTag {
|
||||
c.confirm(confirmed)
|
||||
} else {
|
||||
c.sequencer[confirmed.DeliveryTag] = confirmed
|
||||
}
|
||||
c.resequence()
|
||||
}
|
||||
|
||||
// Multiple confirms all publishings up until the delivery tag
|
||||
func (c *confirms) Multiple(confirmed Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.deferredConfirmations.ConfirmMultiple(confirmed)
|
||||
|
||||
for c.expecting <= confirmed.DeliveryTag {
|
||||
c.confirm(Confirmation{c.expecting, confirmed.Ack})
|
||||
}
|
||||
c.resequence()
|
||||
}
|
||||
|
||||
// Cleans up the confirms struct and its dependencies.
|
||||
// Closes all listeners, discarding any out of sequence confirmations
|
||||
func (c *confirms) Close() error {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.deferredConfirmations.Close()
|
||||
|
||||
for _, l := range c.listeners {
|
||||
close(l)
|
||||
}
|
||||
c.listeners = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
type deferredConfirmations struct {
|
||||
m sync.Mutex
|
||||
confirmations map[uint64]*DeferredConfirmation
|
||||
}
|
||||
|
||||
func newDeferredConfirmations() *deferredConfirmations {
|
||||
return &deferredConfirmations{
|
||||
confirmations: map[uint64]*DeferredConfirmation{},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *deferredConfirmations) Add(tag uint64) *DeferredConfirmation {
|
||||
d.m.Lock()
|
||||
defer d.m.Unlock()
|
||||
|
||||
dc := &DeferredConfirmation{DeliveryTag: tag}
|
||||
dc.done = make(chan struct{})
|
||||
d.confirmations[tag] = dc
|
||||
return dc
|
||||
}
|
||||
|
||||
// remove is only used to drop a tag whose publish failed
|
||||
func (d *deferredConfirmations) remove(tag uint64) {
|
||||
d.m.Lock()
|
||||
defer d.m.Unlock()
|
||||
dc, found := d.confirmations[tag]
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
close(dc.done)
|
||||
delete(d.confirmations, tag)
|
||||
}
|
||||
|
||||
func (d *deferredConfirmations) Confirm(confirmation Confirmation) {
|
||||
d.m.Lock()
|
||||
defer d.m.Unlock()
|
||||
|
||||
dc, found := d.confirmations[confirmation.DeliveryTag]
|
||||
if !found {
|
||||
// We should never receive a confirmation for a tag that hasn't
|
||||
// been published, but a test causes this to happen.
|
||||
return
|
||||
}
|
||||
dc.setAck(confirmation.Ack)
|
||||
delete(d.confirmations, confirmation.DeliveryTag)
|
||||
}
|
||||
|
||||
func (d *deferredConfirmations) ConfirmMultiple(confirmation Confirmation) {
|
||||
d.m.Lock()
|
||||
defer d.m.Unlock()
|
||||
|
||||
for k, v := range d.confirmations {
|
||||
if k <= confirmation.DeliveryTag {
|
||||
v.setAck(confirmation.Ack)
|
||||
delete(d.confirmations, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close nacks all pending DeferredConfirmations being blocked by dc.Wait().
|
||||
func (d *deferredConfirmations) Close() {
|
||||
d.m.Lock()
|
||||
defer d.m.Unlock()
|
||||
|
||||
for k, v := range d.confirmations {
|
||||
v.setAck(false)
|
||||
delete(d.confirmations, k)
|
||||
}
|
||||
}
|
||||
|
||||
// setAck sets the acknowledgement status of the confirmation. Note that it must
|
||||
// not be called more than once.
|
||||
func (d *DeferredConfirmation) setAck(ack bool) {
|
||||
d.ack = ack
|
||||
close(d.done)
|
||||
}
|
||||
|
||||
// Done returns the channel that can be used to wait for the publisher
|
||||
// confirmation.
|
||||
func (d *DeferredConfirmation) Done() <-chan struct{} {
|
||||
return d.done
|
||||
}
|
||||
|
||||
// Acked returns the publisher confirmation in a non-blocking manner. It returns
|
||||
// false if the confirmation was not acknowledged yet or received negative
|
||||
// acknowledgement.
|
||||
func (d *DeferredConfirmation) Acked() bool {
|
||||
select {
|
||||
case <-d.done:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return d.ack
|
||||
}
|
||||
|
||||
// Wait blocks until the publisher confirmation. It returns true if the server
|
||||
// successfully received the publishing.
|
||||
func (d *DeferredConfirmation) Wait() bool {
|
||||
<-d.done
|
||||
return d.ack
|
||||
}
|
||||
|
||||
// WaitContext waits until the publisher confirmation. It returns true if the
|
||||
// server successfully received the publishing. If the context expires before
|
||||
// that, ctx.Err() is returned.
|
||||
func (d *DeferredConfirmation) WaitContext(ctx context.Context) (bool, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false, ctx.Err()
|
||||
case <-d.done:
|
||||
}
|
||||
return d.ack, nil
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -23,11 +27,12 @@ const (
|
||||
|
||||
defaultHeartbeat = 10 * time.Second
|
||||
defaultConnectionTimeout = 30 * time.Second
|
||||
defaultProduct = "https://github.com/streadway/amqp"
|
||||
defaultVersion = "β"
|
||||
defaultProduct = "AMQP 0.9.1 Client"
|
||||
buildVersion = "1.10.0"
|
||||
platform = "golang"
|
||||
// Safer default that makes channel leaks a lot easier to spot
|
||||
// before they create operational headaches. See https://github.com/rabbitmq/rabbitmq-server/issues/1593.
|
||||
defaultChannelMax = (2 << 10) - 1
|
||||
defaultChannelMax = uint16((2 << 10) - 1)
|
||||
defaultLocale = "en_US"
|
||||
)
|
||||
|
||||
@@ -44,7 +49,7 @@ type Config struct {
|
||||
// bindings on the server. Dial sets this to the path parsed from the URL.
|
||||
Vhost string
|
||||
|
||||
ChannelMax int // 0 max channels means 2^16 - 1
|
||||
ChannelMax uint16 // 0 max channels means 2^16 - 1
|
||||
FrameSize int // 0 max bytes means unlimited
|
||||
Heartbeat time.Duration // less than 1s uses the server's interval
|
||||
|
||||
@@ -71,6 +76,17 @@ type Config struct {
|
||||
Dial func(network, addr string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// NewConnectionProperties creates an amqp.Table to be used as amqp.Config.Properties.
|
||||
//
|
||||
// Defaults to library-defined values. For empty properties, use make(amqp.Table) instead.
|
||||
func NewConnectionProperties() Table {
|
||||
return Table{
|
||||
"product": defaultProduct,
|
||||
"version": buildVersion,
|
||||
"platform": platform,
|
||||
}
|
||||
}
|
||||
|
||||
// Connection manages the serialization and deserialization of frames from IO
|
||||
// and dispatches the frames to the appropriate channel. All RPC methods and
|
||||
// asynchronous Publishing, Delivery, Ack, Nack and Return messages are
|
||||
@@ -96,6 +112,8 @@ type Connection struct {
|
||||
blocks []chan Blocking
|
||||
|
||||
errors chan *Error
|
||||
// if connection is closed should close this chan
|
||||
close chan struct{}
|
||||
|
||||
Config Config // The negotiated Config after connection.open
|
||||
|
||||
@@ -139,8 +157,7 @@ func DefaultDial(connectionTimeout time.Duration) func(network, addr string) (ne
|
||||
// scheme. It is equivalent to calling DialTLS(amqp, nil).
|
||||
func Dial(url string) (*Connection, error) {
|
||||
return DialConfig(url, Config{
|
||||
Heartbeat: defaultHeartbeat,
|
||||
Locale: defaultLocale,
|
||||
Locale: defaultLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -151,16 +168,33 @@ func Dial(url string) (*Connection, error) {
|
||||
// DialTLS uses the provided tls.Config when encountering an amqps:// scheme.
|
||||
func DialTLS(url string, amqps *tls.Config) (*Connection, error) {
|
||||
return DialConfig(url, Config{
|
||||
Heartbeat: defaultHeartbeat,
|
||||
TLSClientConfig: amqps,
|
||||
Locale: defaultLocale,
|
||||
})
|
||||
}
|
||||
|
||||
// DialTLS_ExternalAuth accepts a string in the AMQP URI format and returns a
|
||||
// new Connection over TCP using EXTERNAL auth. Defaults to a server heartbeat
|
||||
// interval of 10 seconds and sets the initial read deadline to 30 seconds.
|
||||
//
|
||||
// This mechanism is used, when RabbitMQ is configured for EXTERNAL auth with
|
||||
// ssl_cert_login plugin for userless/passwordless logons
|
||||
//
|
||||
// DialTLS_ExternalAuth uses the provided tls.Config when encountering an
|
||||
// amqps:// scheme.
|
||||
func DialTLS_ExternalAuth(url string, amqps *tls.Config) (*Connection, error) {
|
||||
return DialConfig(url, Config{
|
||||
TLSClientConfig: amqps,
|
||||
SASL: []Authentication{&ExternalAuth{}},
|
||||
})
|
||||
}
|
||||
|
||||
// DialConfig accepts a string in the AMQP URI format and a configuration for
|
||||
// the transport and connection setup, returning a new Connection. Defaults to
|
||||
// a server heartbeat interval of 10 seconds and sets the initial read deadline
|
||||
// to 30 seconds.
|
||||
// to 30 seconds. The heartbeat interval specified in the AMQP URI takes precedence
|
||||
// over the value specified in the config. To disable heartbeats, you must use
|
||||
// the AMQP URI and set heartbeat=0 there.
|
||||
func DialConfig(url string, config Config) (*Connection, error) {
|
||||
var err error
|
||||
var conn net.Conn
|
||||
@@ -171,18 +205,50 @@ func DialConfig(url string, config Config) (*Connection, error) {
|
||||
}
|
||||
|
||||
if config.SASL == nil {
|
||||
config.SASL = []Authentication{uri.PlainAuth()}
|
||||
if uri.AuthMechanism != nil {
|
||||
for _, identifier := range uri.AuthMechanism {
|
||||
switch strings.ToUpper(identifier) {
|
||||
case "PLAIN":
|
||||
config.SASL = append(config.SASL, uri.PlainAuth())
|
||||
case "AMQPLAIN":
|
||||
config.SASL = append(config.SASL, uri.AMQPlainAuth())
|
||||
case "EXTERNAL":
|
||||
config.SASL = append(config.SASL, &ExternalAuth{})
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported auth_mechanism: %v", identifier)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
config.SASL = []Authentication{uri.PlainAuth()}
|
||||
}
|
||||
}
|
||||
|
||||
if config.Vhost == "" {
|
||||
config.Vhost = uri.Vhost
|
||||
}
|
||||
|
||||
if uri.Heartbeat.hasValue {
|
||||
config.Heartbeat = uri.Heartbeat.value
|
||||
} else {
|
||||
if config.Heartbeat == 0 {
|
||||
config.Heartbeat = defaultHeartbeat
|
||||
}
|
||||
}
|
||||
|
||||
if config.ChannelMax == 0 {
|
||||
config.ChannelMax = uri.ChannelMax
|
||||
}
|
||||
|
||||
connectionTimeout := defaultConnectionTimeout
|
||||
if uri.ConnectionTimeout != 0 {
|
||||
connectionTimeout = time.Duration(uri.ConnectionTimeout) * time.Millisecond
|
||||
}
|
||||
|
||||
addr := net.JoinHostPort(uri.Host, strconv.FormatInt(int64(uri.Port), 10))
|
||||
|
||||
dialer := config.Dial
|
||||
if dialer == nil {
|
||||
dialer = DefaultDial(defaultConnectionTimeout)
|
||||
dialer = DefaultDial(connectionTimeout)
|
||||
}
|
||||
|
||||
conn, err = dialer("tcp", addr)
|
||||
@@ -192,7 +258,11 @@ func DialConfig(url string, config Config) (*Connection, error) {
|
||||
|
||||
if uri.Scheme == "amqps" {
|
||||
if config.TLSClientConfig == nil {
|
||||
config.TLSClientConfig = new(tls.Config)
|
||||
tlsConfig, err := tlsConfigFromURI(uri)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create TLS config from URI: %w", err)
|
||||
}
|
||||
config.TLSClientConfig = tlsConfig
|
||||
}
|
||||
|
||||
// If ServerName has not been specified in TLSClientConfig,
|
||||
@@ -203,7 +273,6 @@ func DialConfig(url string, config Config) (*Connection, error) {
|
||||
|
||||
client := tls.Client(conn, config.TLSClientConfig)
|
||||
if err := client.Handshake(); err != nil {
|
||||
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
@@ -218,7 +287,6 @@ func DialConfig(url string, config Config) (*Connection, error) {
|
||||
Open accepts an already established connection, or other io.ReadWriteCloser as
|
||||
a transport. Use this method if you have established a TLS connection or wish
|
||||
to use your own custom transport.
|
||||
|
||||
*/
|
||||
func Open(conn io.ReadWriteCloser, config Config) (*Connection, error) {
|
||||
c := &Connection{
|
||||
@@ -228,12 +296,29 @@ func Open(conn io.ReadWriteCloser, config Config) (*Connection, error) {
|
||||
rpc: make(chan message),
|
||||
sends: make(chan time.Time),
|
||||
errors: make(chan *Error, 1),
|
||||
close: make(chan struct{}),
|
||||
deadlines: make(chan readDeadliner, 1),
|
||||
}
|
||||
go c.reader(conn)
|
||||
return c, c.open(config)
|
||||
}
|
||||
|
||||
/*
|
||||
UpdateSecret updates the secret used to authenticate this connection. It is used when
|
||||
secrets have an expiration date and need to be renewed, like OAuth 2 tokens.
|
||||
|
||||
It returns an error if the operation is not successful, or if the connection is closed.
|
||||
*/
|
||||
func (c *Connection) UpdateSecret(newSecret, reason string) error {
|
||||
if c.IsClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
return c.call(&connectionUpdateSecret{
|
||||
NewSecret: newSecret,
|
||||
Reason: reason,
|
||||
}, &connectionUpdateSecretOk{})
|
||||
}
|
||||
|
||||
/*
|
||||
LocalAddr returns the local TCP peer address, or ":0" (the zero value of net.TCPAddr)
|
||||
as a fallback default value if the underlying transport does not support LocalAddr().
|
||||
@@ -247,6 +332,18 @@ func (c *Connection) LocalAddr() net.Addr {
|
||||
return &net.TCPAddr{}
|
||||
}
|
||||
|
||||
/*
|
||||
RemoteAddr returns the remote TCP peer address, if known.
|
||||
*/
|
||||
func (c *Connection) RemoteAddr() net.Addr {
|
||||
if conn, ok := c.conn.(interface {
|
||||
RemoteAddr() net.Addr
|
||||
}); ok {
|
||||
return conn.RemoteAddr()
|
||||
}
|
||||
return &net.TCPAddr{}
|
||||
}
|
||||
|
||||
// ConnectionState returns basic TLS details of the underlying transport.
|
||||
// Returns a zero value when the underlying connection does not implement
|
||||
// ConnectionState() tls.ConnectionState.
|
||||
@@ -263,11 +360,14 @@ func (c *Connection) ConnectionState() tls.ConnectionState {
|
||||
NotifyClose registers a listener for close events either initiated by an error
|
||||
accompanying a connection.close method or by a normal shutdown.
|
||||
|
||||
On normal shutdowns, the chan will be closed.
|
||||
The chan provided will be closed when the Connection is closed and on a
|
||||
graceful close, no error will be sent.
|
||||
|
||||
In case of a non graceful close the error will be notified synchronously by the library
|
||||
so that it will be necessary to consume the Channel from the caller in order to avoid deadlocks
|
||||
|
||||
To reconnect after a transport or protocol error, register a listener here and
|
||||
re-run your setup process.
|
||||
|
||||
*/
|
||||
func (c *Connection) NotifyClose(receiver chan *Error) chan *Error {
|
||||
c.m.Lock()
|
||||
@@ -291,7 +391,6 @@ become free again.
|
||||
|
||||
This optional extension is supported by the server when the
|
||||
"connection.blocked" server capability key is true.
|
||||
|
||||
*/
|
||||
func (c *Connection) NotifyBlocked(receiver chan Blocking) chan Blocking {
|
||||
c.m.Lock()
|
||||
@@ -334,12 +433,47 @@ func (c *Connection) Close() error {
|
||||
)
|
||||
}
|
||||
|
||||
// CloseDeadline requests and waits for the response to close this AMQP connection.
|
||||
//
|
||||
// Accepts a deadline for waiting the server response. The deadline is passed
|
||||
// to the low-level connection i.e. network socket.
|
||||
//
|
||||
// Regardless of the error returned, the connection is considered closed, and it
|
||||
// should not be used after calling this function.
|
||||
//
|
||||
// In the event of an I/O timeout, connection-closed listeners are NOT informed.
|
||||
//
|
||||
// After returning from this call, all resources associated with this connection,
|
||||
// including the underlying io, Channels, Notify listeners and Channel consumers
|
||||
// will also be closed.
|
||||
func (c *Connection) CloseDeadline(deadline time.Time) error {
|
||||
if c.IsClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
|
||||
defer c.shutdown(nil)
|
||||
|
||||
err := c.setDeadline(deadline)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.call(
|
||||
&connectionClose{
|
||||
ReplyCode: replySuccess,
|
||||
ReplyText: "kthxbai",
|
||||
},
|
||||
&connectionCloseOk{},
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Connection) closeWith(err *Error) error {
|
||||
if c.IsClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
|
||||
defer c.shutdown(err)
|
||||
|
||||
return c.call(
|
||||
&connectionClose{
|
||||
ReplyCode: uint16(err.Code),
|
||||
@@ -352,7 +486,19 @@ func (c *Connection) closeWith(err *Error) error {
|
||||
// IsClosed returns true if the connection is marked as closed, otherwise false
|
||||
// is returned.
|
||||
func (c *Connection) IsClosed() bool {
|
||||
return (atomic.LoadInt32(&c.closed) == 1)
|
||||
return atomic.LoadInt32(&c.closed) == 1
|
||||
}
|
||||
|
||||
// setDeadline is a wrapper to type assert Connection.conn and set an I/O
|
||||
// deadline in the underlying TCP connection socket, by calling
|
||||
// net.Conn.SetDeadline(). It returns an error, in case the type assertion fails,
|
||||
// although this should never happen.
|
||||
func (c *Connection) setDeadline(t time.Time) error {
|
||||
con, ok := c.conn.(net.Conn)
|
||||
if !ok {
|
||||
return errInvalidTypeAssertion
|
||||
}
|
||||
return con.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *Connection) send(f frame) error {
|
||||
@@ -383,6 +529,74 @@ func (c *Connection) send(f frame) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// This method is intended to be used with sendUnflushed() to end a sequence
|
||||
// of sendUnflushed() calls and flush the connection
|
||||
func (c *Connection) endSendUnflushed() error {
|
||||
c.sendM.Lock()
|
||||
defer c.sendM.Unlock()
|
||||
return c.flush()
|
||||
}
|
||||
|
||||
// sendUnflushed performs an *Unflushed* write. It is otherwise equivalent to
|
||||
// send(), and we provide a separate flush() function to explicitly flush the
|
||||
// buffer after all Frames are written.
|
||||
//
|
||||
// Why is this a thing?
|
||||
//
|
||||
// send() method uses writer.WriteFrame(), which will write the Frame then
|
||||
// flush the buffer. For cases like the sendOpen() method on Channel, which
|
||||
// sends multiple Frames (methodFrame, headerFrame, N x bodyFrame), flushing
|
||||
// after each Frame is inefficient as it negates much of the benefit of using a
|
||||
// buffered writer, and results in more syscalls than necessary. Flushing buffers
|
||||
// after every frame can have a significant performance impact when sending
|
||||
// (basicPublish) small messages, so this method performs an *Unflushed* write
|
||||
// but is otherwise equivalent to send() method, and we provide a separate
|
||||
// flush method to explicitly flush the buffer after all Frames are written.
|
||||
func (c *Connection) sendUnflushed(f frame) error {
|
||||
if c.IsClosed() {
|
||||
return ErrClosed
|
||||
}
|
||||
|
||||
c.sendM.Lock()
|
||||
err := c.writer.WriteFrameNoFlush(f)
|
||||
c.sendM.Unlock()
|
||||
|
||||
if err != nil {
|
||||
// shutdown could be re-entrant from signaling notify chans
|
||||
go c.shutdown(&Error{
|
||||
Code: FrameError,
|
||||
Reason: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// This method is intended to be used with sendUnflushed() to explicitly flush
|
||||
// the buffer after all required Frames have been written to the buffer.
|
||||
func (c *Connection) flush() (err error) {
|
||||
if buf, ok := c.writer.w.(*bufio.Writer); ok {
|
||||
err = buf.Flush()
|
||||
|
||||
// Moving send notifier to flush increases basicPublish for the small message
|
||||
// case. As sendUnflushed + flush is used for the case of sending semantically
|
||||
// related Frames (e.g. a Message like basicPublish) there is no real advantage
|
||||
// to sending per Frame vice per "group of related Frames" and for the case of
|
||||
// small messages time.Now() is (relatively) expensive.
|
||||
if err == nil {
|
||||
// Broadcast we sent a frame, reducing heartbeats, only
|
||||
// if there is something that can receive - like a non-reentrant
|
||||
// call or if the heartbeater isn't running
|
||||
select {
|
||||
case c.sends <- time.Now():
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Connection) shutdown(err *Error) {
|
||||
atomic.StoreInt32(&c.closed, 1)
|
||||
|
||||
@@ -394,9 +608,6 @@ func (c *Connection) shutdown(err *Error) {
|
||||
for _, c := range c.closes {
|
||||
c <- err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.errors <- err
|
||||
}
|
||||
// Shutdown handler goroutine can still receive the result.
|
||||
@@ -420,9 +631,11 @@ func (c *Connection) shutdown(err *Error) {
|
||||
}
|
||||
|
||||
c.conn.Close()
|
||||
// reader exit
|
||||
close(c.close)
|
||||
|
||||
c.channels = map[uint16]*Channel{}
|
||||
c.allocator = newAllocator(1, c.Config.ChannelMax)
|
||||
c.channels = nil
|
||||
c.allocator = nil
|
||||
c.noNotify = true
|
||||
})
|
||||
}
|
||||
@@ -443,11 +656,10 @@ func (c *Connection) dispatch0(f frame) {
|
||||
switch m := mf.Method.(type) {
|
||||
case *connectionClose:
|
||||
// Send immediately as shutdown will close our side of the writer.
|
||||
c.send(&methodFrame{
|
||||
ChannelId: 0,
|
||||
Method: &connectionCloseOk{},
|
||||
})
|
||||
|
||||
f := &methodFrame{ChannelId: 0, Method: &connectionCloseOk{}}
|
||||
if err := c.send(f); err != nil {
|
||||
Logger.Printf("error sending connectionCloseOk, error: %+v", err)
|
||||
}
|
||||
c.shutdown(newError(m.ReplyCode, m.ReplyText))
|
||||
case *connectionBlocked:
|
||||
for _, c := range c.blocks {
|
||||
@@ -458,22 +670,39 @@ func (c *Connection) dispatch0(f frame) {
|
||||
c <- Blocking{Active: false}
|
||||
}
|
||||
default:
|
||||
c.rpc <- m
|
||||
select {
|
||||
case <-c.close:
|
||||
return
|
||||
case c.rpc <- m:
|
||||
}
|
||||
|
||||
}
|
||||
case *heartbeatFrame:
|
||||
// kthx - all reads reset our deadline. so we can drop this
|
||||
default:
|
||||
// lolwat - channel0 only responds to methods and heartbeats
|
||||
c.closeWith(ErrUnexpectedFrame)
|
||||
// closeWith use call don't block reader
|
||||
go func() {
|
||||
if err := c.closeWith(ErrUnexpectedFrame); err != nil {
|
||||
Logger.Printf("error sending connectionCloseOk with ErrUnexpectedFrame, error: %+v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Connection) dispatchN(f frame) {
|
||||
c.m.Lock()
|
||||
channel := c.channels[f.channel()]
|
||||
channel, ok := c.channels[f.channel()]
|
||||
if ok {
|
||||
updateChannel(f, channel)
|
||||
} else {
|
||||
Logger.Printf("[debug] dropping frame, channel %d does not exist", f.channel())
|
||||
}
|
||||
c.m.Unlock()
|
||||
|
||||
if channel != nil {
|
||||
// Note: this could result in concurrent dispatch depending on
|
||||
// how channels are managed in an application
|
||||
if ok {
|
||||
channel.recv(channel, f)
|
||||
} else {
|
||||
c.dispatchClosed(f)
|
||||
@@ -496,15 +725,20 @@ func (c *Connection) dispatchClosed(f frame) {
|
||||
if mf, ok := f.(*methodFrame); ok {
|
||||
switch mf.Method.(type) {
|
||||
case *channelClose:
|
||||
c.send(&methodFrame{
|
||||
ChannelId: f.channel(),
|
||||
Method: &channelCloseOk{},
|
||||
})
|
||||
f := &methodFrame{ChannelId: f.channel(), Method: &channelCloseOk{}}
|
||||
if err := c.send(f); err != nil {
|
||||
Logger.Printf("error sending channelCloseOk, channel id: %d error: %+v", f.channel(), err)
|
||||
}
|
||||
case *channelCloseOk:
|
||||
// we are already closed, so do nothing
|
||||
default:
|
||||
// unexpected method on closed channel
|
||||
c.closeWith(ErrClosed)
|
||||
// closeWith use call don't block reader
|
||||
go func() {
|
||||
if err := c.closeWith(ErrClosed); err != nil {
|
||||
Logger.Printf("error sending connectionCloseOk with ErrClosed, error: %+v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,6 +751,8 @@ func (c *Connection) reader(r io.Reader) {
|
||||
frames := &reader{buf}
|
||||
conn, haveDeadliner := r.(readDeadliner)
|
||||
|
||||
defer close(c.rpc)
|
||||
|
||||
for {
|
||||
frame, err := frames.ReadFrame()
|
||||
|
||||
@@ -576,7 +812,13 @@ func (c *Connection) heartbeater(interval time.Duration, done chan *Error) {
|
||||
// When reading, reset our side of the deadline, if we've negotiated one with
|
||||
// a deadline that covers at least 2 server heartbeats
|
||||
if interval > 0 {
|
||||
conn.SetReadDeadline(time.Now().Add(maxServerHeartbeatsInFlight * interval))
|
||||
if err := conn.SetReadDeadline(time.Now().Add(maxServerHeartbeatsInFlight * interval)); err != nil {
|
||||
var opErr *net.OpError
|
||||
if !errors.As(err, &opErr) {
|
||||
Logger.Printf("error setting read deadline in heartbeater: %+v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case <-done:
|
||||
@@ -618,12 +860,17 @@ func (c *Connection) allocateChannel() (*Channel, error) {
|
||||
|
||||
// releaseChannel removes a channel from the registry as the final part of the
|
||||
// channel lifecycle
|
||||
func (c *Connection) releaseChannel(id uint16) {
|
||||
func (c *Connection) releaseChannel(ch *Channel) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
delete(c.channels, id)
|
||||
c.allocator.release(int(id))
|
||||
if !c.IsClosed() {
|
||||
got, ok := c.channels[ch.id]
|
||||
if ok && got == ch {
|
||||
delete(c.channels, ch.id)
|
||||
c.allocator.release(int(ch.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// openChannel allocates and opens a channel, must be paired with closeChannel
|
||||
@@ -634,7 +881,7 @@ func (c *Connection) openChannel() (*Channel, error) {
|
||||
}
|
||||
|
||||
if err := ch.open(); err != nil {
|
||||
c.releaseChannel(ch.id)
|
||||
c.releaseChannel(ch)
|
||||
return nil, err
|
||||
}
|
||||
return ch, nil
|
||||
@@ -645,14 +892,13 @@ func (c *Connection) openChannel() (*Channel, error) {
|
||||
// this connection.
|
||||
func (c *Connection) closeChannel(ch *Channel, e *Error) {
|
||||
ch.shutdown(e)
|
||||
c.releaseChannel(ch.id)
|
||||
c.releaseChannel(ch)
|
||||
}
|
||||
|
||||
/*
|
||||
Channel opens a unique, concurrent server channel to process the bulk of AMQP
|
||||
messages. Any error from methods on this receiver will render the receiver
|
||||
invalid and a new Channel should be opened.
|
||||
|
||||
*/
|
||||
func (c *Connection) Channel() (*Channel, error) {
|
||||
return c.openChannel()
|
||||
@@ -667,39 +913,46 @@ func (c *Connection) call(req message, res ...message) error {
|
||||
}
|
||||
}
|
||||
|
||||
var msg message
|
||||
select {
|
||||
case err, ok := <-c.errors:
|
||||
if !ok {
|
||||
return ErrClosed
|
||||
case e, ok := <-c.errors:
|
||||
if ok {
|
||||
return e
|
||||
}
|
||||
return err
|
||||
|
||||
case msg := <-c.rpc:
|
||||
// Try to match one of the result types
|
||||
for _, try := range res {
|
||||
if reflect.TypeOf(msg) == reflect.TypeOf(try) {
|
||||
// *res = *msg
|
||||
vres := reflect.ValueOf(try).Elem()
|
||||
vmsg := reflect.ValueOf(msg).Elem()
|
||||
vres.Set(vmsg)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrCommandInvalid
|
||||
return ErrClosed
|
||||
case msg = <-c.rpc:
|
||||
}
|
||||
// unreachable
|
||||
|
||||
// Try to match one of the result types
|
||||
for _, try := range res {
|
||||
if reflect.TypeOf(msg) == reflect.TypeOf(try) {
|
||||
// *res = *msg
|
||||
vres := reflect.ValueOf(try).Elem()
|
||||
vmsg := reflect.ValueOf(msg).Elem()
|
||||
vres.Set(vmsg)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrCommandInvalid
|
||||
}
|
||||
|
||||
// Connection = open-Connection *use-Connection close-Connection
|
||||
// open-Connection = C:protocol-header
|
||||
// S:START C:START-OK
|
||||
// *challenge
|
||||
// S:TUNE C:TUNE-OK
|
||||
// C:OPEN S:OPEN-OK
|
||||
// challenge = S:SECURE C:SECURE-OK
|
||||
// use-Connection = *channel
|
||||
// close-Connection = C:CLOSE S:CLOSE-OK
|
||||
// / S:CLOSE C:CLOSE-OK
|
||||
// Communication flow to open, use and close a connection. 'C:' are
|
||||
// frames sent by the Client. 'S:' are frames sent by the Server.
|
||||
//
|
||||
// Connection = open-Connection *use-Connection close-Connection
|
||||
//
|
||||
// open-Connection = C:protocol-header
|
||||
// S:START C:START-OK
|
||||
// *challenge
|
||||
// S:TUNE C:TUNE-OK
|
||||
// C:OPEN S:OPEN-OK
|
||||
//
|
||||
// challenge = S:SECURE C:SECURE-OK
|
||||
//
|
||||
// use-Connection = *channel
|
||||
//
|
||||
// close-Connection = C:CLOSE S:CLOSE-OK
|
||||
// S:CLOSE C:CLOSE-OK
|
||||
func (c *Connection) open(config Config) error {
|
||||
if err := c.send(&protocolHeader{}); err != nil {
|
||||
return err
|
||||
@@ -717,7 +970,7 @@ func (c *Connection) openStart(config Config) error {
|
||||
|
||||
c.Major = int(start.VersionMajor)
|
||||
c.Minor = int(start.VersionMinor)
|
||||
c.Properties = Table(start.ServerProperties)
|
||||
c.Properties = start.ServerProperties
|
||||
c.Locales = strings.Split(start.Locales, " ")
|
||||
|
||||
// eventually support challenge/response here by also responding to
|
||||
@@ -738,15 +991,14 @@ func (c *Connection) openStart(config Config) error {
|
||||
|
||||
func (c *Connection) openTune(config Config, auth Authentication) error {
|
||||
if len(config.Properties) == 0 {
|
||||
config.Properties = Table{
|
||||
"product": defaultProduct,
|
||||
"version": defaultVersion,
|
||||
}
|
||||
config.Properties = NewConnectionProperties()
|
||||
}
|
||||
|
||||
config.Properties["capabilities"] = Table{
|
||||
"connection.blocked": true,
|
||||
"consumer_cancel_notify": true,
|
||||
"basic.nack": true,
|
||||
"publisher_confirms": true,
|
||||
}
|
||||
|
||||
ok := &connectionStartOk{
|
||||
@@ -764,13 +1016,21 @@ func (c *Connection) openTune(config Config, auth Authentication) error {
|
||||
return ErrCredentials
|
||||
}
|
||||
|
||||
// Edge case that may race with c.shutdown()
|
||||
// https://github.com/rabbitmq/amqp091-go/issues/170
|
||||
c.m.Lock()
|
||||
|
||||
// When the server and client both use default 0, then the max channel is
|
||||
// only limited by uint16.
|
||||
c.Config.ChannelMax = pick(config.ChannelMax, int(tune.ChannelMax))
|
||||
c.Config.ChannelMax = pickUInt16(config.ChannelMax, tune.ChannelMax)
|
||||
if c.Config.ChannelMax == 0 {
|
||||
c.Config.ChannelMax = defaultChannelMax
|
||||
}
|
||||
c.Config.ChannelMax = min(c.Config.ChannelMax, maxChannelMax)
|
||||
c.Config.ChannelMax = minUInt16(c.Config.ChannelMax, maxChannelMax)
|
||||
|
||||
c.allocator = newAllocator(1, int(c.Config.ChannelMax))
|
||||
|
||||
c.m.Unlock()
|
||||
|
||||
// Frame size includes headers and end byte (len(payload)+8), even if
|
||||
// this is less than FrameMinSize, use what the server sends because the
|
||||
@@ -784,7 +1044,7 @@ func (c *Connection) openTune(config Config, auth Authentication) error {
|
||||
|
||||
// "The client should start sending heartbeats after receiving a
|
||||
// Connection.Tune method"
|
||||
go c.heartbeater(c.Config.Heartbeat, c.NotifyClose(make(chan *Error, 1)))
|
||||
go c.heartbeater(c.Config.Heartbeat/2, c.NotifyClose(make(chan *Error, 1)))
|
||||
|
||||
if err := c.send(&methodFrame{
|
||||
ChannelId: 0,
|
||||
@@ -826,10 +1086,48 @@ func (c *Connection) openComplete() error {
|
||||
_ = deadliner.SetDeadline(time.Time{})
|
||||
}
|
||||
|
||||
c.allocator = newAllocator(1, c.Config.ChannelMax)
|
||||
return nil
|
||||
}
|
||||
|
||||
// tlsConfigFromURI tries to create TLS configuration based on query parameters.
|
||||
// Returns default (empty) config in case no suitable client cert and/or client key not provided.
|
||||
// Returns error in case certificates can not be parsed.
|
||||
func tlsConfigFromURI(uri URI) (*tls.Config, error) {
|
||||
var certPool *x509.CertPool
|
||||
if uri.CACertFile != "" {
|
||||
data, err := os.ReadFile(uri.CACertFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read CA certificate: %w", err)
|
||||
}
|
||||
|
||||
certPool = x509.NewCertPool()
|
||||
certPool.AppendCertsFromPEM(data)
|
||||
} else if sysPool, err := x509.SystemCertPool(); err != nil {
|
||||
return nil, fmt.Errorf("load system certificates: %w", err)
|
||||
} else {
|
||||
certPool = sysPool
|
||||
}
|
||||
|
||||
if uri.CertFile == "" || uri.KeyFile == "" {
|
||||
// no client auth (mTLS), just server auth
|
||||
return &tls.Config{
|
||||
RootCAs: certPool,
|
||||
ServerName: uri.ServerName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
certificate, err := tls.LoadX509KeyPair(uri.CertFile, uri.KeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load client certificate: %w", err)
|
||||
}
|
||||
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{certificate},
|
||||
RootCAs: certPool,
|
||||
ServerName: uri.ServerName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
@@ -837,6 +1135,13 @@ func max(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
func maxUInt16(a, b uint16) uint16 {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
@@ -844,6 +1149,21 @@ func min(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
func minUInt16(a, b uint16) uint16 {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func pickUInt16(client, server uint16) uint16 {
|
||||
if client == 0 || server == 0 {
|
||||
return maxUInt16(client, server)
|
||||
} else {
|
||||
return minUInt16(client, server)
|
||||
}
|
||||
}
|
||||
|
||||
func pick(client, server int) int {
|
||||
if client == 0 || server == 0 {
|
||||
return max(client, server)
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -75,6 +75,33 @@ func (subs *consumers) buffer(in chan *Delivery, out chan Delivery) {
|
||||
}
|
||||
|
||||
case out <- *queue[0]:
|
||||
/*
|
||||
* https://github.com/rabbitmq/amqp091-go/issues/179
|
||||
* https://github.com/rabbitmq/amqp091-go/pull/180
|
||||
*
|
||||
* Comment from @lars-t-hansen:
|
||||
*
|
||||
* Given Go's slice semantics, and barring any information
|
||||
* available to the compiler that proves that queue is the only
|
||||
* pointer to the memory it references, the only meaning that
|
||||
* queue = queue[1:] can have is basically queue += sizeof(queue
|
||||
* element), ie, it bumps a pointer. Looking at the generated
|
||||
* code for a simple example (on ARM64 in this case) bears this
|
||||
* out. So what we're left with is an array that we have a
|
||||
* pointer into the middle of. When the GC traces this pointer,
|
||||
* it too does not know whether the array has multiple
|
||||
* referents, and so its only sensible choice is to find the
|
||||
* beginning of the array, and if the array is not already
|
||||
* visited, mark every element in it, including the "dead"
|
||||
* pointer.
|
||||
*
|
||||
* (Depending on the program dynamics, an element may eventually
|
||||
* be appended to the queue when the queue is at capacity, and
|
||||
* in this case the live elements are copied into a new array
|
||||
* and the old array is left to be GC'd eventually, along with
|
||||
* the dead object. But that can take time.)
|
||||
*/
|
||||
queue[0] = nil
|
||||
queue = queue[1:]
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
var errDeliveryNotInitialized = errors.New("delivery not initialized")
|
||||
|
||||
// Acknowledger notifies the server of successful or failed consumption of
|
||||
// delivieries via identifier found in the Delivery.DeliveryTag field.
|
||||
// deliveries via identifier found in the Delivery.DeliveryTag field.
|
||||
//
|
||||
// Applications can provide mock implementations in tests of Delivery handlers.
|
||||
type Acknowledger interface {
|
||||
160
vendor/github.com/rabbitmq/amqp091-go/doc.go
generated
vendored
Normal file
160
vendor/github.com/rabbitmq/amqp091-go/doc.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package amqp091 is an AMQP 0.9.1 client with RabbitMQ extensions
|
||||
|
||||
Understand the AMQP 0.9.1 messaging model by reviewing these links first. Much
|
||||
of the terminology in this library directly relates to AMQP concepts.
|
||||
|
||||
Resources
|
||||
|
||||
http://www.rabbitmq.com/tutorials/amqp-concepts.html
|
||||
http://www.rabbitmq.com/getstarted.html
|
||||
http://www.rabbitmq.com/amqp-0-9-1-reference.html
|
||||
|
||||
# Design
|
||||
|
||||
Most other broker clients publish to queues, but in AMQP, clients publish
|
||||
Exchanges instead. AMQP is programmable, meaning that both the producers and
|
||||
consumers agree on the configuration of the broker, instead of requiring an
|
||||
operator or system configuration that declares the logical topology in the
|
||||
broker. The routing between producers and consumer queues is via Bindings.
|
||||
These bindings form the logical topology of the broker.
|
||||
|
||||
In this library, a message sent from publisher is called a "Publishing" and a
|
||||
message received to a consumer is called a "Delivery". The fields of
|
||||
Publishings and Deliveries are close but not exact mappings to the underlying
|
||||
wire format to maintain stronger types. Many other libraries will combine
|
||||
message properties with message headers. In this library, the message well
|
||||
known properties are strongly typed fields on the Publishings and Deliveries,
|
||||
whereas the user defined headers are in the Headers field.
|
||||
|
||||
The method naming closely matches the protocol's method name with positional
|
||||
parameters mapping to named protocol message fields. The motivation here is to
|
||||
present a comprehensive view over all possible interactions with the server.
|
||||
|
||||
Generally, methods that map to protocol methods of the "basic" class will be
|
||||
elided in this interface, and "select" methods of various channel mode selectors
|
||||
will be elided for example Channel.Confirm and Channel.Tx.
|
||||
|
||||
The library is intentionally designed to be synchronous, where responses for
|
||||
each protocol message are required to be received in an RPC manner. Some
|
||||
methods have a noWait parameter like Channel.QueueDeclare, and some methods are
|
||||
asynchronous like Channel.Publish. The error values should still be checked for
|
||||
these methods as they will indicate IO failures like when the underlying
|
||||
connection closes.
|
||||
|
||||
# Asynchronous Events
|
||||
|
||||
Clients of this library may be interested in receiving some of the protocol
|
||||
messages other than Deliveries like basic.ack methods while a channel is in
|
||||
confirm mode.
|
||||
|
||||
The Notify* methods with Connection and Channel receivers model the pattern of
|
||||
asynchronous events like closes due to exceptions, or messages that are sent out
|
||||
of band from an RPC call like basic.ack or basic.flow.
|
||||
|
||||
Any asynchronous events, including Deliveries and Publishings must always have
|
||||
a receiver until the corresponding chans are closed. Without asynchronous
|
||||
receivers, the synchronous methods will block.
|
||||
|
||||
# Use Case
|
||||
|
||||
It's important as a client to an AMQP topology to ensure the state of the
|
||||
broker matches your expectations. For both publish and consume use cases,
|
||||
make sure you declare the queues, exchanges and bindings you expect to exist
|
||||
prior to calling [Channel.PublishWithContext] or [Channel.Consume].
|
||||
|
||||
// Connections start with amqp.Dial() typically from a command line argument
|
||||
// or environment variable.
|
||||
connection, err := amqp.Dial(os.Getenv("AMQP_URL"))
|
||||
|
||||
// To cleanly shutdown by flushing kernel buffers, make sure to close and
|
||||
// wait for the response.
|
||||
defer connection.Close()
|
||||
|
||||
// Most operations happen on a channel. If any error is returned on a
|
||||
// channel, the channel will no longer be valid, throw it away and try with
|
||||
// a different channel. If you use many channels, it's useful for the
|
||||
// server to
|
||||
channel, err := connection.Channel()
|
||||
|
||||
// Declare your topology here, if it doesn't exist, it will be created, if
|
||||
// it existed already and is not what you expect, then that's considered an
|
||||
// error.
|
||||
|
||||
// Use your connection on this topology with either Publish or Consume, or
|
||||
// inspect your queues with QueueInspect. It's unwise to mix Publish and
|
||||
// Consume to let TCP do its job well.
|
||||
|
||||
# SSL/TLS - Secure connections
|
||||
|
||||
When Dial encounters an amqps:// scheme, it will use the zero value of a
|
||||
tls.Config. This will only perform server certificate and host verification.
|
||||
|
||||
Use DialTLS when you wish to provide a client certificate (recommended), include
|
||||
a private certificate authority's certificate in the cert chain for server
|
||||
validity, or run insecure by not verifying the server certificate. DialTLS will
|
||||
use the provided tls.Config when it encounters an amqps:// scheme and will dial
|
||||
a plain connection when it encounters an amqp:// scheme.
|
||||
|
||||
SSL/TLS in RabbitMQ is documented here: http://www.rabbitmq.com/ssl.html
|
||||
|
||||
# Best practises for Connection and Channel notifications:
|
||||
|
||||
In order to be notified when a connection or channel gets closed, both
|
||||
structures offer the possibility to register channels using
|
||||
[Channel.NotifyClose] and [Connection.NotifyClose] functions:
|
||||
|
||||
notifyConnCloseCh := conn.NotifyClose(make(chan *amqp.Error, 1))
|
||||
|
||||
No errors will be sent in case of a graceful connection close. In case of a
|
||||
non-graceful closure due to e.g. network issue, or forced connection closure
|
||||
from the Management UI, the error will be notified synchronously by the library.
|
||||
|
||||
The library sends to notification channels just once. After sending a
|
||||
notification to all channels, the library closes all registered notification
|
||||
channels. After receiving a notification, the application should create and
|
||||
register a new channel. To avoid deadlocks in the library, it is necessary to
|
||||
consume from the channels. This could be done inside a different goroutine with
|
||||
a select listening on the two channels inside a for loop like:
|
||||
|
||||
go func() {
|
||||
for notifyConnClose != nil || notifyChanClose != nil {
|
||||
select {
|
||||
case err, ok := <-notifyConnClose:
|
||||
if !ok {
|
||||
notifyConnClose = nil
|
||||
} else {
|
||||
fmt.Printf("connection closed, error %s", err)
|
||||
}
|
||||
case err, ok := <-notifyChanClose:
|
||||
if !ok {
|
||||
notifyChanClose = nil
|
||||
} else {
|
||||
fmt.Printf("channel closed, error %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
It is strongly recommended to use buffered channels to avoid deadlocks inside
|
||||
the library.
|
||||
|
||||
# Best practises for NotifyPublish notifications:
|
||||
|
||||
Using [Channel.NotifyPublish] allows the caller of the library to be notified,
|
||||
through a go channel, when a message has been received and confirmed by the
|
||||
broker. It's advisable to wait for all Confirmations to arrive before calling
|
||||
[Channel.Close] or [Connection.Close]. It is also necessary to consume from this
|
||||
channel until it gets closed. The library sends synchronously to the registered channel.
|
||||
It is advisable to use a buffered channel, with capacity set to the maximum acceptable
|
||||
number of unconfirmed messages.
|
||||
|
||||
It is important to consume from the confirmation channel at all times, in order to avoid
|
||||
deadlocks in the library.
|
||||
*/
|
||||
package amqp091
|
||||
23
vendor/github.com/rabbitmq/amqp091-go/fuzz.go
generated
vendored
Normal file
23
vendor/github.com/rabbitmq/amqp091-go/fuzz.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package amqp091
|
||||
|
||||
import "bytes"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
r := reader{bytes.NewReader(data)}
|
||||
frame, err := r.ReadFrame()
|
||||
if err != nil {
|
||||
if frame != nil {
|
||||
panic("frame is not nil")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
14
vendor/github.com/rabbitmq/amqp091-go/gen.ps1
generated
vendored
Normal file
14
vendor/github.com/rabbitmq/amqp091-go/gen.ps1
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
$DebugPreference = 'Continue'
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
Set-PSDebug -Off
|
||||
Set-StrictMode -Version 'Latest' -ErrorAction 'Stop' -Verbose
|
||||
|
||||
New-Variable -Name curdir -Option Constant -Value $PSScriptRoot
|
||||
|
||||
$specDir = Resolve-Path -LiteralPath (Join-Path -Path $curdir -ChildPath 'spec')
|
||||
$amqpSpecXml = Resolve-Path -LiteralPath (Join-Path -Path $specDir -ChildPath 'amqp0-9-1.stripped.extended.xml')
|
||||
$gen = Resolve-Path -LiteralPath (Join-Path -Path $specDir -ChildPath 'gen.go')
|
||||
$spec091 = Resolve-Path -LiteralPath (Join-Path -Path $curdir -ChildPath 'spec091.go')
|
||||
|
||||
Get-Content -LiteralPath $amqpSpecXml | go run $gen | gofmt | Set-Content -Force -Path $spec091
|
||||
23
vendor/github.com/rabbitmq/amqp091-go/log.go
generated
vendored
Normal file
23
vendor/github.com/rabbitmq/amqp091-go/log.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2022 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package amqp091
|
||||
|
||||
type Logging interface {
|
||||
Printf(format string, v ...interface{})
|
||||
}
|
||||
|
||||
var Logger Logging = NullLogger{}
|
||||
|
||||
// Enables logging using a custom Logging instance. Note that this is
|
||||
// not thread safe and should be called at application start
|
||||
func SetLogger(logger Logging) {
|
||||
Logger = logger
|
||||
}
|
||||
|
||||
type NullLogger struct {
|
||||
}
|
||||
|
||||
func (l NullLogger) Printf(format string, v ...interface{}) {
|
||||
}
|
||||
76
vendor/github.com/streadway/amqp/read.go → vendor/github.com/rabbitmq/amqp091-go/read.go
generated
vendored
76
vendor/github.com/streadway/amqp/read.go → vendor/github.com/rabbitmq/amqp091-go/read.go
generated
vendored
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -14,29 +14,29 @@ import (
|
||||
)
|
||||
|
||||
/*
|
||||
Reads a frame from an input stream and returns an interface that can be cast into
|
||||
ReadFrame reads a frame from an input stream and returns an interface that can be cast into
|
||||
one of the following:
|
||||
|
||||
methodFrame
|
||||
PropertiesFrame
|
||||
bodyFrame
|
||||
heartbeatFrame
|
||||
methodFrame
|
||||
PropertiesFrame
|
||||
bodyFrame
|
||||
heartbeatFrame
|
||||
|
||||
2.3.5 frame Details
|
||||
|
||||
All frames consist of a header (7 octets), a payload of arbitrary size, and a
|
||||
'frame-end' octet that detects malformed frames:
|
||||
|
||||
0 1 3 7 size+7 size+8
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
| type | channel | size | | payload | | frame-end |
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
octet short long size octets octet
|
||||
0 1 3 7 size+7 size+8
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
| type | channel | size | | payload | | frame-end |
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
octet short long size octets octet
|
||||
|
||||
To read a frame, we:
|
||||
1. Read the header and check the frame type and channel.
|
||||
2. Depending on the frame type, we read the payload and process it.
|
||||
3. Read the frame end octet.
|
||||
1. Read the header and check the frame type and channel.
|
||||
2. Depending on the frame type, we read the payload and process it.
|
||||
3. Read the frame end octet.
|
||||
|
||||
In realistic implementations where performance is a concern, we would use
|
||||
“read-ahead buffering” or
|
||||
@@ -50,7 +50,7 @@ func (r *reader) ReadFrame() (frame frame, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
typ := uint8(scratch[0])
|
||||
typ := scratch[0]
|
||||
channel := binary.BigEndian.Uint16(scratch[1:3])
|
||||
size := binary.BigEndian.Uint32(scratch[3:7])
|
||||
|
||||
@@ -131,20 +131,6 @@ func readDecimal(r io.Reader) (v Decimal, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func readFloat32(r io.Reader) (v float32, err error) {
|
||||
if err = binary.Read(r, binary.BigEndian, &v); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func readFloat64(r io.Reader) (v float64, err error) {
|
||||
if err = binary.Read(r, binary.BigEndian, &v); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func readTimestamp(r io.Reader) (v time.Time, err error) {
|
||||
var sec int64
|
||||
if err = binary.Read(r, binary.BigEndian, &sec); err != nil {
|
||||
@@ -161,7 +147,8 @@ func readTimestamp(r io.Reader) (v time.Time, err error) {
|
||||
'S': string
|
||||
'T': time.Time
|
||||
'V': nil
|
||||
'b': byte
|
||||
'b': int8
|
||||
'B': byte
|
||||
'd': float64
|
||||
'f': float32
|
||||
'l': int64
|
||||
@@ -181,15 +168,22 @@ func readField(r io.Reader) (v interface{}, err error) {
|
||||
if err = binary.Read(r, binary.BigEndian, &value); err != nil {
|
||||
return
|
||||
}
|
||||
return (value != 0), nil
|
||||
return value != 0, nil
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
var value [1]byte
|
||||
if _, err = io.ReadFull(r, value[0:1]); err != nil {
|
||||
return
|
||||
}
|
||||
return value[0], nil
|
||||
|
||||
case 'b':
|
||||
var value int8
|
||||
if err = binary.Read(r, binary.BigEndian, &value); err != nil {
|
||||
return
|
||||
}
|
||||
return value, nil
|
||||
|
||||
case 's':
|
||||
var value int16
|
||||
if err = binary.Read(r, binary.BigEndian, &value); err != nil {
|
||||
@@ -260,12 +254,12 @@ func readField(r io.Reader) (v interface{}, err error) {
|
||||
}
|
||||
|
||||
/*
|
||||
Field tables are long strings that contain packed name-value pairs. The
|
||||
name-value pairs are encoded as short string defining the name, and octet
|
||||
defining the values type and then the value itself. The valid field types for
|
||||
tables are an extension of the native integer, bit, string, and timestamp
|
||||
types, and are shown in the grammar. Multi-octet integer fields are always
|
||||
held in network byte order.
|
||||
Field tables are long strings that contain packed name-value pairs. The
|
||||
name-value pairs are encoded as short string defining the name, and octet
|
||||
defining the values type and then the value itself. The valid field types for
|
||||
tables are an extension of the native integer, bit, string, and timestamp
|
||||
types, and are shown in the grammar. Multi-octet integer fields are always
|
||||
held in network byte order.
|
||||
*/
|
||||
func readTable(r io.Reader) (table Table, err error) {
|
||||
var nested bytes.Buffer
|
||||
@@ -309,7 +303,7 @@ func readArray(r io.Reader) ([]interface{}, error) {
|
||||
|
||||
var (
|
||||
lim = &io.LimitedReader{R: r, N: int64(size)}
|
||||
arr = []interface{}{}
|
||||
arr []interface{}
|
||||
field interface{}
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
/* GENERATED FILE - DO NOT EDIT */
|
||||
/* Rebuild from the spec/gen.go tool */
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@@ -552,6 +552,66 @@ func (msg *connectionUnblocked) read(r io.Reader) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
type connectionUpdateSecret struct {
|
||||
NewSecret string
|
||||
Reason string
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecret) id() (uint16, uint16) {
|
||||
return 10, 70
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecret) wait() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecret) write(w io.Writer) (err error) {
|
||||
|
||||
if err = writeLongstr(w, msg.NewSecret); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = writeShortstr(w, msg.Reason); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecret) read(r io.Reader) (err error) {
|
||||
|
||||
if msg.NewSecret, err = readLongstr(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if msg.Reason, err = readShortstr(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type connectionUpdateSecretOk struct {
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecretOk) id() (uint16, uint16) {
|
||||
return 10, 71
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecretOk) wait() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecretOk) write(w io.Writer) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (msg *connectionUpdateSecretOk) read(r io.Reader) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type channelOpen struct {
|
||||
reserved1 string
|
||||
}
|
||||
@@ -2757,7 +2817,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // connection start
|
||||
//fmt.Println("NextMethod: class:10 method:10")
|
||||
// fmt.Println("NextMethod: class:10 method:10")
|
||||
method := &connectionStart{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2765,7 +2825,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // connection start-ok
|
||||
//fmt.Println("NextMethod: class:10 method:11")
|
||||
// fmt.Println("NextMethod: class:10 method:11")
|
||||
method := &connectionStartOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2773,7 +2833,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // connection secure
|
||||
//fmt.Println("NextMethod: class:10 method:20")
|
||||
// fmt.Println("NextMethod: class:10 method:20")
|
||||
method := &connectionSecure{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2781,7 +2841,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // connection secure-ok
|
||||
//fmt.Println("NextMethod: class:10 method:21")
|
||||
// fmt.Println("NextMethod: class:10 method:21")
|
||||
method := &connectionSecureOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2789,7 +2849,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 30: // connection tune
|
||||
//fmt.Println("NextMethod: class:10 method:30")
|
||||
// fmt.Println("NextMethod: class:10 method:30")
|
||||
method := &connectionTune{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2797,7 +2857,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 31: // connection tune-ok
|
||||
//fmt.Println("NextMethod: class:10 method:31")
|
||||
// fmt.Println("NextMethod: class:10 method:31")
|
||||
method := &connectionTuneOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2805,7 +2865,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 40: // connection open
|
||||
//fmt.Println("NextMethod: class:10 method:40")
|
||||
// fmt.Println("NextMethod: class:10 method:40")
|
||||
method := &connectionOpen{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2813,7 +2873,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 41: // connection open-ok
|
||||
//fmt.Println("NextMethod: class:10 method:41")
|
||||
// fmt.Println("NextMethod: class:10 method:41")
|
||||
method := &connectionOpenOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2821,7 +2881,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 50: // connection close
|
||||
//fmt.Println("NextMethod: class:10 method:50")
|
||||
// fmt.Println("NextMethod: class:10 method:50")
|
||||
method := &connectionClose{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2829,7 +2889,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 51: // connection close-ok
|
||||
//fmt.Println("NextMethod: class:10 method:51")
|
||||
// fmt.Println("NextMethod: class:10 method:51")
|
||||
method := &connectionCloseOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2837,7 +2897,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 60: // connection blocked
|
||||
//fmt.Println("NextMethod: class:10 method:60")
|
||||
// fmt.Println("NextMethod: class:10 method:60")
|
||||
method := &connectionBlocked{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2845,13 +2905,29 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 61: // connection unblocked
|
||||
//fmt.Println("NextMethod: class:10 method:61")
|
||||
// fmt.Println("NextMethod: class:10 method:61")
|
||||
method := &connectionUnblocked{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
}
|
||||
mf.Method = method
|
||||
|
||||
case 70: // connection update-secret
|
||||
// fmt.Println("NextMethod: class:10 method:70")
|
||||
method := &connectionUpdateSecret{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
}
|
||||
mf.Method = method
|
||||
|
||||
case 71: // connection update-secret-ok
|
||||
// fmt.Println("NextMethod: class:10 method:71")
|
||||
method := &connectionUpdateSecretOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
}
|
||||
mf.Method = method
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId)
|
||||
}
|
||||
@@ -2860,7 +2936,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // channel open
|
||||
//fmt.Println("NextMethod: class:20 method:10")
|
||||
// fmt.Println("NextMethod: class:20 method:10")
|
||||
method := &channelOpen{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2868,7 +2944,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // channel open-ok
|
||||
//fmt.Println("NextMethod: class:20 method:11")
|
||||
// fmt.Println("NextMethod: class:20 method:11")
|
||||
method := &channelOpenOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2876,7 +2952,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // channel flow
|
||||
//fmt.Println("NextMethod: class:20 method:20")
|
||||
// fmt.Println("NextMethod: class:20 method:20")
|
||||
method := &channelFlow{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2884,7 +2960,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // channel flow-ok
|
||||
//fmt.Println("NextMethod: class:20 method:21")
|
||||
// fmt.Println("NextMethod: class:20 method:21")
|
||||
method := &channelFlowOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2892,7 +2968,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 40: // channel close
|
||||
//fmt.Println("NextMethod: class:20 method:40")
|
||||
// fmt.Println("NextMethod: class:20 method:40")
|
||||
method := &channelClose{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2900,7 +2976,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 41: // channel close-ok
|
||||
//fmt.Println("NextMethod: class:20 method:41")
|
||||
// fmt.Println("NextMethod: class:20 method:41")
|
||||
method := &channelCloseOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2915,7 +2991,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // exchange declare
|
||||
//fmt.Println("NextMethod: class:40 method:10")
|
||||
// fmt.Println("NextMethod: class:40 method:10")
|
||||
method := &exchangeDeclare{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2923,7 +2999,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // exchange declare-ok
|
||||
//fmt.Println("NextMethod: class:40 method:11")
|
||||
// fmt.Println("NextMethod: class:40 method:11")
|
||||
method := &exchangeDeclareOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2931,7 +3007,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // exchange delete
|
||||
//fmt.Println("NextMethod: class:40 method:20")
|
||||
// fmt.Println("NextMethod: class:40 method:20")
|
||||
method := &exchangeDelete{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2939,7 +3015,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // exchange delete-ok
|
||||
//fmt.Println("NextMethod: class:40 method:21")
|
||||
// fmt.Println("NextMethod: class:40 method:21")
|
||||
method := &exchangeDeleteOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2947,7 +3023,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 30: // exchange bind
|
||||
//fmt.Println("NextMethod: class:40 method:30")
|
||||
// fmt.Println("NextMethod: class:40 method:30")
|
||||
method := &exchangeBind{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2955,7 +3031,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 31: // exchange bind-ok
|
||||
//fmt.Println("NextMethod: class:40 method:31")
|
||||
// fmt.Println("NextMethod: class:40 method:31")
|
||||
method := &exchangeBindOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2963,7 +3039,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 40: // exchange unbind
|
||||
//fmt.Println("NextMethod: class:40 method:40")
|
||||
// fmt.Println("NextMethod: class:40 method:40")
|
||||
method := &exchangeUnbind{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2971,7 +3047,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 51: // exchange unbind-ok
|
||||
//fmt.Println("NextMethod: class:40 method:51")
|
||||
// fmt.Println("NextMethod: class:40 method:51")
|
||||
method := &exchangeUnbindOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2986,7 +3062,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // queue declare
|
||||
//fmt.Println("NextMethod: class:50 method:10")
|
||||
// fmt.Println("NextMethod: class:50 method:10")
|
||||
method := &queueDeclare{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -2994,7 +3070,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // queue declare-ok
|
||||
//fmt.Println("NextMethod: class:50 method:11")
|
||||
// fmt.Println("NextMethod: class:50 method:11")
|
||||
method := &queueDeclareOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3002,7 +3078,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // queue bind
|
||||
//fmt.Println("NextMethod: class:50 method:20")
|
||||
// fmt.Println("NextMethod: class:50 method:20")
|
||||
method := &queueBind{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3010,7 +3086,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // queue bind-ok
|
||||
//fmt.Println("NextMethod: class:50 method:21")
|
||||
// fmt.Println("NextMethod: class:50 method:21")
|
||||
method := &queueBindOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3018,7 +3094,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 50: // queue unbind
|
||||
//fmt.Println("NextMethod: class:50 method:50")
|
||||
// fmt.Println("NextMethod: class:50 method:50")
|
||||
method := &queueUnbind{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3026,7 +3102,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 51: // queue unbind-ok
|
||||
//fmt.Println("NextMethod: class:50 method:51")
|
||||
// fmt.Println("NextMethod: class:50 method:51")
|
||||
method := &queueUnbindOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3034,7 +3110,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 30: // queue purge
|
||||
//fmt.Println("NextMethod: class:50 method:30")
|
||||
// fmt.Println("NextMethod: class:50 method:30")
|
||||
method := &queuePurge{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3042,7 +3118,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 31: // queue purge-ok
|
||||
//fmt.Println("NextMethod: class:50 method:31")
|
||||
// fmt.Println("NextMethod: class:50 method:31")
|
||||
method := &queuePurgeOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3050,7 +3126,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 40: // queue delete
|
||||
//fmt.Println("NextMethod: class:50 method:40")
|
||||
// fmt.Println("NextMethod: class:50 method:40")
|
||||
method := &queueDelete{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3058,7 +3134,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 41: // queue delete-ok
|
||||
//fmt.Println("NextMethod: class:50 method:41")
|
||||
// fmt.Println("NextMethod: class:50 method:41")
|
||||
method := &queueDeleteOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3073,7 +3149,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // basic qos
|
||||
//fmt.Println("NextMethod: class:60 method:10")
|
||||
// fmt.Println("NextMethod: class:60 method:10")
|
||||
method := &basicQos{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3081,7 +3157,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // basic qos-ok
|
||||
//fmt.Println("NextMethod: class:60 method:11")
|
||||
// fmt.Println("NextMethod: class:60 method:11")
|
||||
method := &basicQosOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3089,7 +3165,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // basic consume
|
||||
//fmt.Println("NextMethod: class:60 method:20")
|
||||
// fmt.Println("NextMethod: class:60 method:20")
|
||||
method := &basicConsume{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3097,7 +3173,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // basic consume-ok
|
||||
//fmt.Println("NextMethod: class:60 method:21")
|
||||
// fmt.Println("NextMethod: class:60 method:21")
|
||||
method := &basicConsumeOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3105,7 +3181,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 30: // basic cancel
|
||||
//fmt.Println("NextMethod: class:60 method:30")
|
||||
// fmt.Println("NextMethod: class:60 method:30")
|
||||
method := &basicCancel{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3113,7 +3189,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 31: // basic cancel-ok
|
||||
//fmt.Println("NextMethod: class:60 method:31")
|
||||
// fmt.Println("NextMethod: class:60 method:31")
|
||||
method := &basicCancelOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3121,7 +3197,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 40: // basic publish
|
||||
//fmt.Println("NextMethod: class:60 method:40")
|
||||
// fmt.Println("NextMethod: class:60 method:40")
|
||||
method := &basicPublish{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3129,7 +3205,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 50: // basic return
|
||||
//fmt.Println("NextMethod: class:60 method:50")
|
||||
// fmt.Println("NextMethod: class:60 method:50")
|
||||
method := &basicReturn{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3137,7 +3213,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 60: // basic deliver
|
||||
//fmt.Println("NextMethod: class:60 method:60")
|
||||
// fmt.Println("NextMethod: class:60 method:60")
|
||||
method := &basicDeliver{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3145,7 +3221,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 70: // basic get
|
||||
//fmt.Println("NextMethod: class:60 method:70")
|
||||
// fmt.Println("NextMethod: class:60 method:70")
|
||||
method := &basicGet{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3153,7 +3229,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 71: // basic get-ok
|
||||
//fmt.Println("NextMethod: class:60 method:71")
|
||||
// fmt.Println("NextMethod: class:60 method:71")
|
||||
method := &basicGetOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3161,7 +3237,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 72: // basic get-empty
|
||||
//fmt.Println("NextMethod: class:60 method:72")
|
||||
// fmt.Println("NextMethod: class:60 method:72")
|
||||
method := &basicGetEmpty{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3169,7 +3245,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 80: // basic ack
|
||||
//fmt.Println("NextMethod: class:60 method:80")
|
||||
// fmt.Println("NextMethod: class:60 method:80")
|
||||
method := &basicAck{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3177,7 +3253,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 90: // basic reject
|
||||
//fmt.Println("NextMethod: class:60 method:90")
|
||||
// fmt.Println("NextMethod: class:60 method:90")
|
||||
method := &basicReject{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3185,7 +3261,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 100: // basic recover-async
|
||||
//fmt.Println("NextMethod: class:60 method:100")
|
||||
// fmt.Println("NextMethod: class:60 method:100")
|
||||
method := &basicRecoverAsync{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3193,7 +3269,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 110: // basic recover
|
||||
//fmt.Println("NextMethod: class:60 method:110")
|
||||
// fmt.Println("NextMethod: class:60 method:110")
|
||||
method := &basicRecover{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3201,7 +3277,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 111: // basic recover-ok
|
||||
//fmt.Println("NextMethod: class:60 method:111")
|
||||
// fmt.Println("NextMethod: class:60 method:111")
|
||||
method := &basicRecoverOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3209,7 +3285,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 120: // basic nack
|
||||
//fmt.Println("NextMethod: class:60 method:120")
|
||||
// fmt.Println("NextMethod: class:60 method:120")
|
||||
method := &basicNack{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3224,7 +3300,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // tx select
|
||||
//fmt.Println("NextMethod: class:90 method:10")
|
||||
// fmt.Println("NextMethod: class:90 method:10")
|
||||
method := &txSelect{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3232,7 +3308,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // tx select-ok
|
||||
//fmt.Println("NextMethod: class:90 method:11")
|
||||
// fmt.Println("NextMethod: class:90 method:11")
|
||||
method := &txSelectOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3240,7 +3316,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 20: // tx commit
|
||||
//fmt.Println("NextMethod: class:90 method:20")
|
||||
// fmt.Println("NextMethod: class:90 method:20")
|
||||
method := &txCommit{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3248,7 +3324,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 21: // tx commit-ok
|
||||
//fmt.Println("NextMethod: class:90 method:21")
|
||||
// fmt.Println("NextMethod: class:90 method:21")
|
||||
method := &txCommitOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3256,7 +3332,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 30: // tx rollback
|
||||
//fmt.Println("NextMethod: class:90 method:30")
|
||||
// fmt.Println("NextMethod: class:90 method:30")
|
||||
method := &txRollback{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3264,7 +3340,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 31: // tx rollback-ok
|
||||
//fmt.Println("NextMethod: class:90 method:31")
|
||||
// fmt.Println("NextMethod: class:90 method:31")
|
||||
method := &txRollbackOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3279,7 +3355,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
switch mf.MethodId {
|
||||
|
||||
case 10: // confirm select
|
||||
//fmt.Println("NextMethod: class:85 method:10")
|
||||
// fmt.Println("NextMethod: class:85 method:10")
|
||||
method := &confirmSelect{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
@@ -3287,7 +3363,7 @@ func (r *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err err
|
||||
mf.Method = method
|
||||
|
||||
case 11: // confirm select-ok
|
||||
//fmt.Println("NextMethod: class:85 method:11")
|
||||
// fmt.Println("NextMethod: class:85 method:11")
|
||||
method := &confirmSelectOk{}
|
||||
if err = method.read(r.r); err != nil {
|
||||
return
|
||||
272
vendor/github.com/streadway/amqp/types.go → vendor/github.com/rabbitmq/amqp091-go/types.go
generated
vendored
272
vendor/github.com/streadway/amqp/types.go → vendor/github.com/rabbitmq/amqp091-go/types.go
generated
vendored
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -11,6 +11,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultExchange is the default direct exchange that binds every queue by its
|
||||
// name. Applications can route to a queue using the queue name as routing key.
|
||||
const DefaultExchange = ""
|
||||
|
||||
// Constants for standard AMQP 0-9-1 exchange types.
|
||||
const (
|
||||
ExchangeDirect = "direct"
|
||||
@@ -29,7 +33,7 @@ var (
|
||||
ErrChannelMax = &Error{Code: ChannelError, Reason: "channel id space exhausted"}
|
||||
|
||||
// ErrSASL is returned from Dial when the authentication mechanism could not
|
||||
// be negoated.
|
||||
// be negotiated.
|
||||
ErrSASL = &Error{Code: AccessRefused, Reason: "SASL could not negotiate a shared mechanism"}
|
||||
|
||||
// ErrCredentials is returned when the authenticated client is not authorized
|
||||
@@ -61,6 +65,11 @@ var (
|
||||
ErrFieldType = &Error{Code: SyntaxError, Reason: "unsupported table field type"}
|
||||
)
|
||||
|
||||
// internal errors used inside the library
|
||||
var (
|
||||
errInvalidTypeAssertion = &Error{Code: InternalError, Reason: "type assertion unsuccessful", Server: false, Recover: true}
|
||||
)
|
||||
|
||||
// Error captures the code and reason a channel or connection has been closed
|
||||
// by the server.
|
||||
type Error struct {
|
||||
@@ -135,6 +144,19 @@ const (
|
||||
flagReserved1 = 0x0004
|
||||
)
|
||||
|
||||
// Expiration. These constants can be used to set a messages expiration TTL.
|
||||
// They should be viewed as a clarification of the expiration functionality in
|
||||
// messages and their usage is not enforced by this pkg.
|
||||
//
|
||||
// The server requires a string value that is interpreted by the server as
|
||||
// milliseconds. If no value is set, which translates to the nil value of
|
||||
// string, the message will never expire by itself. This does not influence queue
|
||||
// configured TTL configurations.
|
||||
const (
|
||||
NeverExpire string = "" // empty value means never expire
|
||||
ImmediatelyExpire string = "0" // 0 means immediately expire
|
||||
)
|
||||
|
||||
// Queue captures the current server state of the queue on the server returned
|
||||
// from Channel.QueueDeclare or Channel.QueueInspect.
|
||||
type Queue struct {
|
||||
@@ -153,18 +175,25 @@ type Publishing struct {
|
||||
Headers Table
|
||||
|
||||
// Properties
|
||||
ContentType string // MIME content type
|
||||
ContentEncoding string // MIME content encoding
|
||||
DeliveryMode uint8 // Transient (0 or 1) or Persistent (2)
|
||||
Priority uint8 // 0 to 9
|
||||
CorrelationId string // correlation identifier
|
||||
ReplyTo string // address to to reply to (ex: RPC)
|
||||
Expiration string // message expiration spec
|
||||
MessageId string // message identifier
|
||||
Timestamp time.Time // message timestamp
|
||||
Type string // message type name
|
||||
UserId string // creating user id - ex: "guest"
|
||||
AppId string // creating application id
|
||||
ContentType string // MIME content type
|
||||
ContentEncoding string // MIME content encoding
|
||||
DeliveryMode uint8 // Transient (0 or 1) or Persistent (2)
|
||||
Priority uint8 // 0 to 9
|
||||
CorrelationId string // correlation identifier
|
||||
ReplyTo string // address to to reply to (ex: RPC)
|
||||
// Expiration represents the message TTL in milliseconds. A value of "0"
|
||||
// indicates that the message will immediately expire if the message arrives
|
||||
// at its destination and the message is not directly handled by a consumer
|
||||
// that currently has the capacatity to do so. If you wish the message to
|
||||
// not expire on its own, set this value to any ttl value, empty string or
|
||||
// use the corresponding constants NeverExpire and ImmediatelyExpire. This
|
||||
// does not influence queue configured TTL values.
|
||||
Expiration string
|
||||
MessageId string // message identifier
|
||||
Timestamp time.Time // message timestamp
|
||||
Type string // message type name
|
||||
UserId string // creating user id - ex: "guest"
|
||||
AppId string // creating application id
|
||||
|
||||
// The application specific payload of the message
|
||||
Body []byte
|
||||
@@ -179,6 +208,16 @@ type Blocking struct {
|
||||
Reason string // Server reason for activation
|
||||
}
|
||||
|
||||
// DeferredConfirmation represents a future publisher confirm for a message. It
|
||||
// allows users to directly correlate a publishing to a confirmation. These are
|
||||
// returned from PublishWithDeferredConfirm on Channels.
|
||||
type DeferredConfirmation struct {
|
||||
DeliveryTag uint64
|
||||
|
||||
done chan struct{}
|
||||
ack bool
|
||||
}
|
||||
|
||||
// Confirmation notifies the acknowledgment or negative acknowledgement of a
|
||||
// publishing identified by its delivery tag. Use NotifyPublish on the Channel
|
||||
// to consume these events.
|
||||
@@ -194,23 +233,106 @@ type Decimal struct {
|
||||
Value int32
|
||||
}
|
||||
|
||||
// Most common queue argument keys in queue declaration. For a comprehensive list
|
||||
// of queue arguments, visit [RabbitMQ Queue docs].
|
||||
//
|
||||
// [QueueTypeArg] queue argument is used to declare quorum and stream queues.
|
||||
// Accepted values are [QueueTypeClassic] (default), [QueueTypeQuorum] and
|
||||
// [QueueTypeStream]. [Quorum Queues] accept (almost) all queue arguments as their
|
||||
// Classic Queues counterparts. Check [feature comparison] docs for more
|
||||
// information.
|
||||
//
|
||||
// Queues can define their [max length] using [QueueMaxLenArg] and
|
||||
// [QueueMaxLenBytesArg] queue arguments. Overflow behaviour is set using
|
||||
// [QueueOverflowArg]. Accepted values are [QueueOverflowDropHead] (default),
|
||||
// [QueueOverflowRejectPublish] and [QueueOverflowRejectPublishDLX].
|
||||
//
|
||||
// [Queue TTL] can be defined using [QueueTTLArg]. That is, the time-to-live for an
|
||||
// unused queue. [Queue Message TTL] can be defined using [QueueMessageTTLArg].
|
||||
// This will set a time-to-live for messages in the queue.
|
||||
//
|
||||
// [Stream retention] can be configured using [StreamMaxLenBytesArg], to set the
|
||||
// maximum size of the stream. Please note that stream queues always keep, at
|
||||
// least, one segment. [Stream retention] can also be set using [StreamMaxAgeArg],
|
||||
// to set time-based retention. Values are string with unit suffix. Valid
|
||||
// suffixes are Y, M, D, h, m, s. E.g. "7D" for one week. The maximum segment
|
||||
// size can be set using [StreamMaxSegmentSizeBytesArg]. The default value is
|
||||
// 500_000_000 bytes ~= 500 megabytes
|
||||
//
|
||||
// Starting with RabbitMQ 3.12, consumer timeout can be configured as a queue
|
||||
// argument. This is the timeout for a consumer to acknowledge a message. The
|
||||
// value is the time in milliseconds. The timeout is evaluated periodically,
|
||||
// at one minute intervals. Values lower than one minute are not supported.
|
||||
// See the [consumer timeout] guide for more information.
|
||||
//
|
||||
// [Single Active Consumer] on quorum and classic queues can be configured
|
||||
// using [SingleActiveConsumerArg]. This argument expects a boolean value. It is
|
||||
// false by default.
|
||||
//
|
||||
// [RabbitMQ Queue docs]: https://rabbitmq.com/queues.html
|
||||
// [Stream retention]: https://rabbitmq.com/streams.html#retention
|
||||
// [max length]: https://rabbitmq.com/maxlength.html
|
||||
// [Queue TTL]: https://rabbitmq.com/ttl.html#queue-ttl
|
||||
// [Queue Message TTL]: https://rabbitmq.com/ttl.html#per-queue-message-ttl
|
||||
// [Quorum Queues]: https://rabbitmq.com/quorum-queues.html
|
||||
// [feature comparison]: https://rabbitmq.com/quorum-queues.html#feature-comparison
|
||||
// [consumer timeout]: https://rabbitmq.com/consumers.html#acknowledgement-timeout
|
||||
// [Single Active Consumer]: https://rabbitmq.com/consumers.html#single-active-consumer
|
||||
const (
|
||||
QueueTypeArg = "x-queue-type"
|
||||
QueueMaxLenArg = "x-max-length"
|
||||
QueueMaxLenBytesArg = "x-max-length-bytes"
|
||||
StreamMaxLenBytesArg = "x-max-length-bytes"
|
||||
QueueOverflowArg = "x-overflow"
|
||||
QueueMessageTTLArg = "x-message-ttl"
|
||||
QueueTTLArg = "x-expires"
|
||||
StreamMaxAgeArg = "x-max-age"
|
||||
StreamMaxSegmentSizeBytesArg = "x-stream-max-segment-size-bytes"
|
||||
// QueueVersionArg declares the Classic Queue version to use. Expects an integer, either 1 or 2.
|
||||
QueueVersionArg = "x-queue-version"
|
||||
// ConsumerTimeoutArg is available in RabbitMQ 3.12+ as a queue argument.
|
||||
ConsumerTimeoutArg = "x-consumer-timeout"
|
||||
SingleActiveConsumerArg = "x-single-active-consumer"
|
||||
)
|
||||
|
||||
// Values for queue arguments. Use as values for queue arguments during queue declaration.
|
||||
// The following argument table will create a classic queue, with max length set to 100 messages,
|
||||
// and a queue TTL of 30 minutes.
|
||||
//
|
||||
// args := amqp.Table{
|
||||
// amqp.QueueTypeArg: QueueTypeClassic,
|
||||
// amqp.QueueMaxLenArg: 100,
|
||||
// amqp.QueueTTLArg: 1800000,
|
||||
// }
|
||||
//
|
||||
// Refer to [Channel.QueueDeclare] for more examples.
|
||||
const (
|
||||
QueueTypeClassic = "classic"
|
||||
QueueTypeQuorum = "quorum"
|
||||
QueueTypeStream = "stream"
|
||||
QueueOverflowDropHead = "drop-head"
|
||||
QueueOverflowRejectPublish = "reject-publish"
|
||||
QueueOverflowRejectPublishDLX = "reject-publish-dlx"
|
||||
)
|
||||
|
||||
// Table stores user supplied fields of the following types:
|
||||
//
|
||||
// bool
|
||||
// byte
|
||||
// float32
|
||||
// float64
|
||||
// int
|
||||
// int16
|
||||
// int32
|
||||
// int64
|
||||
// nil
|
||||
// string
|
||||
// time.Time
|
||||
// amqp.Decimal
|
||||
// amqp.Table
|
||||
// []byte
|
||||
// []interface{} - containing above types
|
||||
// bool
|
||||
// byte
|
||||
// int8
|
||||
// float32
|
||||
// float64
|
||||
// int
|
||||
// int16
|
||||
// int32
|
||||
// int64
|
||||
// nil
|
||||
// string
|
||||
// time.Time
|
||||
// amqp.Decimal
|
||||
// amqp.Table
|
||||
// []byte
|
||||
// []interface{} - containing above types
|
||||
//
|
||||
// Functions taking a table will immediately fail when the table contains a
|
||||
// value of an unsupported type.
|
||||
@@ -221,12 +343,11 @@ type Decimal struct {
|
||||
// Use a type assertion when reading values from a table for type conversion.
|
||||
//
|
||||
// RabbitMQ expects int32 for integer values.
|
||||
//
|
||||
type Table map[string]interface{}
|
||||
|
||||
func validateField(f interface{}) error {
|
||||
switch fv := f.(type) {
|
||||
case nil, bool, byte, int, int16, int32, int64, float32, float64, string, []byte, Decimal, time.Time:
|
||||
case nil, bool, byte, int8, int, int16, int32, int64, float32, float64, string, []byte, Decimal, time.Time:
|
||||
return nil
|
||||
|
||||
case []interface{}:
|
||||
@@ -254,17 +375,12 @@ func (t Table) Validate() error {
|
||||
return validateField(t)
|
||||
}
|
||||
|
||||
// Heap interface for maintaining delivery tags
|
||||
type tagSet []uint64
|
||||
|
||||
func (set tagSet) Len() int { return len(set) }
|
||||
func (set tagSet) Less(i, j int) bool { return (set)[i] < (set)[j] }
|
||||
func (set tagSet) Swap(i, j int) { (set)[i], (set)[j] = (set)[j], (set)[i] }
|
||||
func (set *tagSet) Push(tag interface{}) { *set = append(*set, tag.(uint64)) }
|
||||
func (set *tagSet) Pop() interface{} {
|
||||
val := (*set)[len(*set)-1]
|
||||
*set = (*set)[:len(*set)-1]
|
||||
return val
|
||||
// Sets the connection name property. This property can be used in
|
||||
// amqp.Config to set a custom connection name during amqp.DialConfig(). This
|
||||
// can be helpful to identify specific connections in RabbitMQ, for debugging or
|
||||
// tracing purposes.
|
||||
func (t Table) SetClientConnectionName(connName string) {
|
||||
t["connection_name"] = connName
|
||||
}
|
||||
|
||||
type message interface {
|
||||
@@ -288,11 +404,11 @@ The base interface implemented as:
|
||||
All frames consist of a header (7 octets), a payload of arbitrary size, and a 'frame-end' octet that detects
|
||||
malformed frames:
|
||||
|
||||
0 1 3 7 size+7 size+8
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
| type | channel | size | | payload | | frame-end |
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
octet short long size octets octet
|
||||
0 1 3 7 size+7 size+8
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
| type | channel | size | | payload | | frame-end |
|
||||
+------+---------+-------------+ +------------+ +-----------+
|
||||
octet short long size octets octet
|
||||
|
||||
To read a frame, we:
|
||||
|
||||
@@ -303,13 +419,24 @@ To read a frame, we:
|
||||
In realistic implementations where performance is a concern, we would use
|
||||
“read-ahead buffering” or “gathering reads” to avoid doing three separate
|
||||
system calls to read a frame.
|
||||
|
||||
*/
|
||||
type frame interface {
|
||||
write(io.Writer) error
|
||||
channel() uint16
|
||||
}
|
||||
|
||||
/*
|
||||
Perform any updates on the channel immediately after the frame is decoded while the
|
||||
connection mutex is held.
|
||||
*/
|
||||
func updateChannel(f frame, channel *Channel) {
|
||||
if mf, isMethodFrame := f.(*methodFrame); isMethodFrame {
|
||||
if _, isChannelClose := mf.Method.(*channelClose); isChannelClose {
|
||||
channel.setClosed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type reader struct {
|
||||
r io.Reader
|
||||
}
|
||||
@@ -334,17 +461,17 @@ func (protocolHeader) channel() uint16 {
|
||||
Method frames carry the high-level protocol commands (which we call "methods").
|
||||
One method frame carries one command. The method frame payload has this format:
|
||||
|
||||
0 2 4
|
||||
+----------+-----------+-------------- - -
|
||||
| class-id | method-id | arguments...
|
||||
+----------+-----------+-------------- - -
|
||||
short short ...
|
||||
0 2 4
|
||||
+----------+-----------+-------------- - -
|
||||
| class-id | method-id | arguments...
|
||||
+----------+-----------+-------------- - -
|
||||
short short ...
|
||||
|
||||
To process a method frame, we:
|
||||
1. Read the method frame payload.
|
||||
2. Unpack it into a structure. A given method always has the same structure,
|
||||
so we can unpack the method rapidly. 3. Check that the method is allowed in
|
||||
the current context.
|
||||
so we can unpack the method rapidly. 3. Check that the method is allowed in
|
||||
the current context.
|
||||
4. Check that the method arguments are valid.
|
||||
5. Execute the method.
|
||||
|
||||
@@ -383,11 +510,11 @@ follows it with a content header and zero or more content body frames.
|
||||
|
||||
A content header frame has this format:
|
||||
|
||||
0 2 4 12 14
|
||||
+----------+--------+-----------+----------------+------------- - -
|
||||
| class-id | weight | body size | property flags | property list...
|
||||
+----------+--------+-----------+----------------+------------- - -
|
||||
short short long long short remainder...
|
||||
0 2 4 12 14
|
||||
+----------+--------+-----------+----------------+------------- - -
|
||||
| class-id | weight | body size | property flags | property list...
|
||||
+----------+--------+-----------+----------------+------------- - -
|
||||
short short long long short remainder...
|
||||
|
||||
We place content body in distinct frames (rather than including it in the
|
||||
method) so that AMQP may support "zero copy" techniques in which content is
|
||||
@@ -415,10 +542,10 @@ into several (or many) chunks, each forming a "content body frame".
|
||||
Looking at the frames for a specific channel, as they pass on the wire, we
|
||||
might see something like this:
|
||||
|
||||
[method]
|
||||
[method] [header] [body] [body]
|
||||
[method]
|
||||
...
|
||||
[method]
|
||||
[method] [header] [body] [body]
|
||||
[method]
|
||||
...
|
||||
*/
|
||||
type bodyFrame struct {
|
||||
ChannelId uint16
|
||||
@@ -426,3 +553,16 @@ type bodyFrame struct {
|
||||
}
|
||||
|
||||
func (f *bodyFrame) channel() uint16 { return f.ChannelId }
|
||||
|
||||
type heartbeatDuration struct {
|
||||
value time.Duration
|
||||
hasValue bool
|
||||
}
|
||||
|
||||
func newHeartbeatDurationFromSeconds(s int) heartbeatDuration {
|
||||
v := time.Duration(s) * time.Second
|
||||
return heartbeatDuration{
|
||||
value: v,
|
||||
hasValue: true,
|
||||
}
|
||||
}
|
||||
114
vendor/github.com/streadway/amqp/uri.go → vendor/github.com/rabbitmq/amqp091-go/uri.go
generated
vendored
114
vendor/github.com/streadway/amqp/uri.go → vendor/github.com/rabbitmq/amqp091-go/uri.go
generated
vendored
@@ -1,12 +1,13 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -32,12 +33,20 @@ var defaultURI = URI{
|
||||
|
||||
// URI represents a parsed AMQP URI string.
|
||||
type URI struct {
|
||||
Scheme string
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
Vhost string
|
||||
Scheme string
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
Vhost string
|
||||
CertFile string // client TLS auth - path to certificate (PEM)
|
||||
CACertFile string // client TLS auth - path to CA certificate (PEM)
|
||||
KeyFile string // client TLS auth - path to private key (PEM)
|
||||
ServerName string // client TLS auth - server name
|
||||
AuthMechanism []string
|
||||
Heartbeat heartbeatDuration
|
||||
ConnectionTimeout int
|
||||
ChannelMax uint16
|
||||
}
|
||||
|
||||
// ParseURI attempts to parse the given AMQP URI according to the spec.
|
||||
@@ -45,17 +54,32 @@ type URI struct {
|
||||
//
|
||||
// Default values for the fields are:
|
||||
//
|
||||
// Scheme: amqp
|
||||
// Host: localhost
|
||||
// Port: 5672
|
||||
// Username: guest
|
||||
// Password: guest
|
||||
// Vhost: /
|
||||
// Scheme: amqp
|
||||
// Host: localhost
|
||||
// Port: 5672
|
||||
// Username: guest
|
||||
// Password: guest
|
||||
// Vhost: /
|
||||
//
|
||||
// Supports TLS query parameters. See https://www.rabbitmq.com/uri-query-parameters.html
|
||||
//
|
||||
// certfile: <path/to/client_cert.pem>
|
||||
// keyfile: <path/to/client_key.pem>
|
||||
// cacertfile: <path/to/ca.pem>
|
||||
// server_name_indication: <server name>
|
||||
// auth_mechanism: <one or more: plain, amqplain, external>
|
||||
// heartbeat: <seconds (integer)>
|
||||
// connection_timeout: <milliseconds (integer)>
|
||||
// channel_max: <max number of channels (integer)>
|
||||
//
|
||||
// If cacertfile is not provided, system CA certificates will be used.
|
||||
// Mutual TLS (client auth) will be enabled only in case keyfile AND certfile provided.
|
||||
//
|
||||
// If Config.TLSClientConfig is set, TLS parameters from URI will be ignored.
|
||||
func ParseURI(uri string) (URI, error) {
|
||||
builder := defaultURI
|
||||
|
||||
if strings.Contains(uri, " ") == true {
|
||||
if strings.Contains(uri, " ") {
|
||||
return builder, errURIWhitespace
|
||||
}
|
||||
|
||||
@@ -113,6 +137,38 @@ func ParseURI(uri string) (URI, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// see https://www.rabbitmq.com/uri-query-parameters.html
|
||||
params := u.Query()
|
||||
builder.CertFile = params.Get("certfile")
|
||||
builder.KeyFile = params.Get("keyfile")
|
||||
builder.CACertFile = params.Get("cacertfile")
|
||||
builder.ServerName = params.Get("server_name_indication")
|
||||
builder.AuthMechanism = params["auth_mechanism"]
|
||||
|
||||
if params.Has("heartbeat") {
|
||||
value, err := strconv.Atoi(params.Get("heartbeat"))
|
||||
if err != nil {
|
||||
return builder, fmt.Errorf("heartbeat is not an integer: %v", err)
|
||||
}
|
||||
builder.Heartbeat = newHeartbeatDurationFromSeconds(value)
|
||||
}
|
||||
|
||||
if params.Has("connection_timeout") {
|
||||
value, err := strconv.Atoi(params.Get("connection_timeout"))
|
||||
if err != nil {
|
||||
return builder, fmt.Errorf("connection_timeout is not an integer: %v", err)
|
||||
}
|
||||
builder.ConnectionTimeout = value
|
||||
}
|
||||
|
||||
if params.Has("channel_max") {
|
||||
value, err := strconv.ParseUint(params.Get("channel_max"), 10, 16)
|
||||
if err != nil {
|
||||
return builder, fmt.Errorf("connection_timeout is not an integer: %v", err)
|
||||
}
|
||||
builder.ChannelMax = uint16(value)
|
||||
}
|
||||
|
||||
return builder, nil
|
||||
}
|
||||
|
||||
@@ -150,8 +206,6 @@ func (uri URI) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
authority.Host = net.JoinHostPort(uri.Host, strconv.Itoa(uri.Port))
|
||||
|
||||
if defaultPort, found := schemePorts[uri.Scheme]; !found || defaultPort != uri.Port {
|
||||
authority.Host = net.JoinHostPort(uri.Host, strconv.Itoa(uri.Port))
|
||||
} else {
|
||||
@@ -172,5 +226,29 @@ func (uri URI) String() string {
|
||||
authority.Path = "/"
|
||||
}
|
||||
|
||||
if uri.CertFile != "" || uri.KeyFile != "" || uri.CACertFile != "" || uri.ServerName != "" {
|
||||
rawQuery := strings.Builder{}
|
||||
if uri.CertFile != "" {
|
||||
rawQuery.WriteString("certfile=")
|
||||
rawQuery.WriteString(uri.CertFile)
|
||||
rawQuery.WriteRune('&')
|
||||
}
|
||||
if uri.KeyFile != "" {
|
||||
rawQuery.WriteString("keyfile=")
|
||||
rawQuery.WriteString(uri.KeyFile)
|
||||
rawQuery.WriteRune('&')
|
||||
}
|
||||
if uri.CACertFile != "" {
|
||||
rawQuery.WriteString("cacertfile=")
|
||||
rawQuery.WriteString(uri.CACertFile)
|
||||
rawQuery.WriteRune('&')
|
||||
}
|
||||
if uri.ServerName != "" {
|
||||
rawQuery.WriteString("server_name_indication=")
|
||||
rawQuery.WriteString(uri.ServerName)
|
||||
}
|
||||
authority.RawQuery = rawQuery.String()
|
||||
}
|
||||
|
||||
return authority.String()
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Copyright (c) 2021 VMware, Inc. or its affiliates. All Rights Reserved.
|
||||
// Copyright (c) 2012-2021, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
package amqp
|
||||
package amqp091
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -15,6 +15,11 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func (w *writer) WriteFrameNoFlush(frame frame) (err error) {
|
||||
err = frame.write(w.w)
|
||||
return
|
||||
}
|
||||
|
||||
func (w *writer) WriteFrame(frame frame) (err error) {
|
||||
if err = frame.write(w.w); err != nil {
|
||||
return
|
||||
@@ -63,11 +68,10 @@ func (f *heartbeatFrame) write(w io.Writer) (err error) {
|
||||
// +----------+--------+-----------+----------------+------------- - -
|
||||
// | class-id | weight | body size | property flags | property list...
|
||||
// +----------+--------+-----------+----------------+------------- - -
|
||||
// short short long long short remainder...
|
||||
//
|
||||
// short short long long short remainder...
|
||||
func (f *headerFrame) write(w io.Writer) (err error) {
|
||||
var payload bytes.Buffer
|
||||
var zeroTime time.Time
|
||||
|
||||
if err = binary.Write(&payload, binary.BigEndian, f.ClassId); err != nil {
|
||||
return
|
||||
@@ -113,7 +117,7 @@ func (f *headerFrame) write(w io.Writer) (err error) {
|
||||
if len(f.Properties.MessageId) > 0 {
|
||||
mask = mask | flagMessageId
|
||||
}
|
||||
if f.Properties.Timestamp != zeroTime {
|
||||
if !f.Properties.Timestamp.IsZero() {
|
||||
mask = mask | flagTimestamp
|
||||
}
|
||||
if len(f.Properties.Type) > 0 {
|
||||
@@ -212,7 +216,7 @@ func writeFrame(w io.Writer, typ uint8, channel uint16, payload []byte) (err err
|
||||
size := uint(len(payload))
|
||||
|
||||
_, err = w.Write([]byte{
|
||||
byte(typ),
|
||||
typ,
|
||||
byte((channel & 0xff00) >> 8),
|
||||
byte((channel & 0x00ff) >> 0),
|
||||
byte((size & 0xff000000) >> 24),
|
||||
@@ -276,7 +280,8 @@ func writeLongstr(w io.Writer, s string) (err error) {
|
||||
'S': string
|
||||
'T': time.Time
|
||||
'V': nil
|
||||
'b': byte
|
||||
'b': int8
|
||||
'B': byte
|
||||
'd': float64
|
||||
'f': float32
|
||||
'l': int64
|
||||
@@ -299,8 +304,13 @@ func writeField(w io.Writer, value interface{}) (err error) {
|
||||
enc = buf[:2]
|
||||
|
||||
case byte:
|
||||
buf[0] = 'B'
|
||||
buf[1] = v
|
||||
enc = buf[:2]
|
||||
|
||||
case int8:
|
||||
buf[0] = 'b'
|
||||
buf[1] = byte(v)
|
||||
buf[1] = uint8(v)
|
||||
enc = buf[:2]
|
||||
|
||||
case int16:
|
||||
@@ -335,7 +345,7 @@ func writeField(w io.Writer, value interface{}) (err error) {
|
||||
|
||||
case Decimal:
|
||||
buf[0] = 'D'
|
||||
buf[1] = byte(v.Scale)
|
||||
buf[1] = v.Scale
|
||||
binary.BigEndian.PutUint32(buf[2:6], uint32(v.Value))
|
||||
enc = buf[:6]
|
||||
|
||||
@@ -412,5 +422,5 @@ func writeTable(w io.Writer, table Table) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
return writeLongstr(w, string(buf.Bytes()))
|
||||
return writeLongstr(w, buf.String())
|
||||
}
|
||||
12
vendor/github.com/streadway/amqp/.gitignore
generated
vendored
12
vendor/github.com/streadway/amqp/.gitignore
generated
vendored
@@ -1,12 +0,0 @@
|
||||
certs/*
|
||||
spec/spec
|
||||
examples/simple-consumer/simple-consumer
|
||||
examples/simple-producer/simple-producer
|
||||
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
.idea/**/contentModel.xml
|
||||
25
vendor/github.com/streadway/amqp/.travis.yml
generated
vendored
25
vendor/github.com/streadway/amqp/.travis.yml
generated
vendored
@@ -1,25 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- rabbitmq-server
|
||||
|
||||
services:
|
||||
- rabbitmq
|
||||
|
||||
env:
|
||||
- GO111MODULE=on AMQP_URL=amqp://guest:guest@127.0.0.1:5672/
|
||||
|
||||
before_install:
|
||||
- go get -v golang.org/x/lint/golint
|
||||
|
||||
script:
|
||||
- ./pre-commit
|
||||
- go test -cpu=1,2 -v -tags integration ./...
|
||||
35
vendor/github.com/streadway/amqp/CONTRIBUTING.md
generated
vendored
35
vendor/github.com/streadway/amqp/CONTRIBUTING.md
generated
vendored
@@ -1,35 +0,0 @@
|
||||
## Prequisites
|
||||
|
||||
1. Go: [https://golang.org/dl/](https://golang.org/dl/)
|
||||
1. Golint `go get -u -v github.com/golang/lint/golint`
|
||||
|
||||
## Contributing
|
||||
|
||||
The workflow is pretty standard:
|
||||
|
||||
1. Fork github.com/streadway/amqp
|
||||
1. Add the pre-commit hook: `ln -s ../../pre-commit .git/hooks/pre-commit`
|
||||
1. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
1. Run integration tests (see below)
|
||||
1. **Implement tests**
|
||||
1. Implement fixs
|
||||
1. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
1. Push to a branch (`git push -u origin my-new-feature`)
|
||||
1. Submit a pull request
|
||||
|
||||
## Running Tests
|
||||
|
||||
The test suite assumes that:
|
||||
|
||||
* A RabbitMQ node is running on localhost with all defaults: [https://www.rabbitmq.com/download.html](https://www.rabbitmq.com/download.html)
|
||||
* `AMQP_URL` is exported to `amqp://guest:guest@127.0.0.1:5672/`
|
||||
|
||||
### Integration Tests
|
||||
|
||||
After starting a local RabbitMQ, run integration tests with the following:
|
||||
|
||||
env AMQP_URL=amqp://guest:guest@127.0.0.1:5672/ go test -v -cpu 2 -tags integration -race
|
||||
|
||||
All integration tests should use the `integrationConnection(...)` test
|
||||
helpers defined in `integration_test.go` to setup the integration environment
|
||||
and logging.
|
||||
100
vendor/github.com/streadway/amqp/README.md
generated
vendored
100
vendor/github.com/streadway/amqp/README.md
generated
vendored
@@ -1,100 +0,0 @@
|
||||
[](http://travis-ci.org/streadway/amqp) [](http://godoc.org/github.com/streadway/amqp)
|
||||
|
||||
# Go RabbitMQ Client Library (Unmaintained Fork)
|
||||
|
||||
## Beware of Abandonware
|
||||
|
||||
This repository is **NOT ACTIVELY MAINTAINED**. Consider using
|
||||
a different fork instead: [rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go).
|
||||
In case of questions, start a discussion in that repo or [use other RabbitMQ community resources](https://rabbitmq.com/contact.html).
|
||||
|
||||
|
||||
|
||||
## Project Maturity
|
||||
|
||||
This project has been used in production systems for many years. As of 2022,
|
||||
this repository is **NOT ACTIVELY MAINTAINED**.
|
||||
|
||||
This repository is **very strict** about any potential public API changes.
|
||||
You may want to consider [rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go) which
|
||||
is more willing to adapt the API.
|
||||
|
||||
|
||||
## Supported Go Versions
|
||||
|
||||
This library supports two most recent Go release series, currently 1.10 and 1.11.
|
||||
|
||||
|
||||
## Supported RabbitMQ Versions
|
||||
|
||||
This project supports RabbitMQ versions starting with `2.0` but primarily tested
|
||||
against reasonably recent `3.x` releases. Some features and behaviours may be
|
||||
server version-specific.
|
||||
|
||||
## Goals
|
||||
|
||||
Provide a functional interface that closely represents the AMQP 0.9.1 model
|
||||
targeted to RabbitMQ as a server. This includes the minimum necessary to
|
||||
interact the semantics of the protocol.
|
||||
|
||||
## Non-goals
|
||||
|
||||
Things not intended to be supported.
|
||||
|
||||
* Auto reconnect and re-synchronization of client and server topologies.
|
||||
* Reconnection would require understanding the error paths when the
|
||||
topology cannot be declared on reconnect. This would require a new set
|
||||
of types and code paths that are best suited at the call-site of this
|
||||
package. AMQP has a dynamic topology that needs all peers to agree. If
|
||||
this doesn't happen, the behavior is undefined. Instead of producing a
|
||||
possible interface with undefined behavior, this package is designed to
|
||||
be simple for the caller to implement the necessary connection-time
|
||||
topology declaration so that reconnection is trivial and encapsulated in
|
||||
the caller's application code.
|
||||
* AMQP Protocol negotiation for forward or backward compatibility.
|
||||
* 0.9.1 is stable and widely deployed. Versions 0.10 and 1.0 are divergent
|
||||
specifications that change the semantics and wire format of the protocol.
|
||||
We will accept patches for other protocol support but have no plans for
|
||||
implementation ourselves.
|
||||
* Anything other than PLAIN and EXTERNAL authentication mechanisms.
|
||||
* Keeping the mechanisms interface modular makes it possible to extend
|
||||
outside of this package. If other mechanisms prove to be popular, then
|
||||
we would accept patches to include them in this package.
|
||||
|
||||
## Usage
|
||||
|
||||
See the 'examples' subdirectory for simple producers and consumers executables.
|
||||
If you have a use-case in mind which isn't well-represented by the examples,
|
||||
please file an issue.
|
||||
|
||||
## Documentation
|
||||
|
||||
Use [Godoc documentation](http://godoc.org/github.com/streadway/amqp) for
|
||||
reference and usage.
|
||||
|
||||
[RabbitMQ tutorials in
|
||||
Go](https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/go) are also
|
||||
available.
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are very much welcomed. Create your pull request on a non-master
|
||||
branch, make sure a test or example is included that covers your change and
|
||||
your commits represent coherent changes that include a reason for the change.
|
||||
|
||||
To run the integration tests, make sure you have RabbitMQ running on any host,
|
||||
export the environment variable `AMQP_URL=amqp://host/` and run `go test -tags
|
||||
integration`. TravisCI will also run the integration tests.
|
||||
|
||||
Thanks to the [community of contributors](https://github.com/streadway/amqp/graphs/contributors).
|
||||
|
||||
## External packages
|
||||
|
||||
* [Google App Engine Dialer support](https://github.com/soundtrackyourbrand/gaeamqp)
|
||||
* [RabbitMQ examples in Go](https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/go)
|
||||
|
||||
## License
|
||||
|
||||
BSD 2 clause - see LICENSE for more details.
|
||||
|
||||
|
||||
94
vendor/github.com/streadway/amqp/confirms.go
generated
vendored
94
vendor/github.com/streadway/amqp/confirms.go
generated
vendored
@@ -1,94 +0,0 @@
|
||||
package amqp
|
||||
|
||||
import "sync"
|
||||
|
||||
// confirms resequences and notifies one or multiple publisher confirmation listeners
|
||||
type confirms struct {
|
||||
m sync.Mutex
|
||||
listeners []chan Confirmation
|
||||
sequencer map[uint64]Confirmation
|
||||
published uint64
|
||||
expecting uint64
|
||||
}
|
||||
|
||||
// newConfirms allocates a confirms
|
||||
func newConfirms() *confirms {
|
||||
return &confirms{
|
||||
sequencer: map[uint64]Confirmation{},
|
||||
published: 0,
|
||||
expecting: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *confirms) Listen(l chan Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.listeners = append(c.listeners, l)
|
||||
}
|
||||
|
||||
// publish increments the publishing counter
|
||||
func (c *confirms) Publish() uint64 {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
c.published++
|
||||
return c.published
|
||||
}
|
||||
|
||||
// confirm confirms one publishing, increments the expecting delivery tag, and
|
||||
// removes bookkeeping for that delivery tag.
|
||||
func (c *confirms) confirm(confirmation Confirmation) {
|
||||
delete(c.sequencer, c.expecting)
|
||||
c.expecting++
|
||||
for _, l := range c.listeners {
|
||||
l <- confirmation
|
||||
}
|
||||
}
|
||||
|
||||
// resequence confirms any out of order delivered confirmations
|
||||
func (c *confirms) resequence() {
|
||||
for c.expecting <= c.published {
|
||||
sequenced, found := c.sequencer[c.expecting]
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
c.confirm(sequenced)
|
||||
}
|
||||
}
|
||||
|
||||
// one confirms one publishing and all following in the publishing sequence
|
||||
func (c *confirms) One(confirmed Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
if c.expecting == confirmed.DeliveryTag {
|
||||
c.confirm(confirmed)
|
||||
} else {
|
||||
c.sequencer[confirmed.DeliveryTag] = confirmed
|
||||
}
|
||||
c.resequence()
|
||||
}
|
||||
|
||||
// multiple confirms all publishings up until the delivery tag
|
||||
func (c *confirms) Multiple(confirmed Confirmation) {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
for c.expecting <= confirmed.DeliveryTag {
|
||||
c.confirm(Confirmation{c.expecting, confirmed.Ack})
|
||||
}
|
||||
c.resequence()
|
||||
}
|
||||
|
||||
// Close closes all listeners, discarding any out of sequence confirmations
|
||||
func (c *confirms) Close() error {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
|
||||
for _, l := range c.listeners {
|
||||
close(l)
|
||||
}
|
||||
c.listeners = nil
|
||||
return nil
|
||||
}
|
||||
108
vendor/github.com/streadway/amqp/doc.go
generated
vendored
108
vendor/github.com/streadway/amqp/doc.go
generated
vendored
@@ -1,108 +0,0 @@
|
||||
// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
// Source code and contact info at http://github.com/streadway/amqp
|
||||
|
||||
/*
|
||||
Package amqp is an AMQP 0.9.1 client with RabbitMQ extensions
|
||||
|
||||
Understand the AMQP 0.9.1 messaging model by reviewing these links first. Much
|
||||
of the terminology in this library directly relates to AMQP concepts.
|
||||
|
||||
Resources
|
||||
|
||||
http://www.rabbitmq.com/tutorials/amqp-concepts.html
|
||||
http://www.rabbitmq.com/getstarted.html
|
||||
http://www.rabbitmq.com/amqp-0-9-1-reference.html
|
||||
|
||||
Design
|
||||
|
||||
Most other broker clients publish to queues, but in AMQP, clients publish
|
||||
Exchanges instead. AMQP is programmable, meaning that both the producers and
|
||||
consumers agree on the configuration of the broker, instead of requiring an
|
||||
operator or system configuration that declares the logical topology in the
|
||||
broker. The routing between producers and consumer queues is via Bindings.
|
||||
These bindings form the logical topology of the broker.
|
||||
|
||||
In this library, a message sent from publisher is called a "Publishing" and a
|
||||
message received to a consumer is called a "Delivery". The fields of
|
||||
Publishings and Deliveries are close but not exact mappings to the underlying
|
||||
wire format to maintain stronger types. Many other libraries will combine
|
||||
message properties with message headers. In this library, the message well
|
||||
known properties are strongly typed fields on the Publishings and Deliveries,
|
||||
whereas the user defined headers are in the Headers field.
|
||||
|
||||
The method naming closely matches the protocol's method name with positional
|
||||
parameters mapping to named protocol message fields. The motivation here is to
|
||||
present a comprehensive view over all possible interactions with the server.
|
||||
|
||||
Generally, methods that map to protocol methods of the "basic" class will be
|
||||
elided in this interface, and "select" methods of various channel mode selectors
|
||||
will be elided for example Channel.Confirm and Channel.Tx.
|
||||
|
||||
The library is intentionally designed to be synchronous, where responses for
|
||||
each protocol message are required to be received in an RPC manner. Some
|
||||
methods have a noWait parameter like Channel.QueueDeclare, and some methods are
|
||||
asynchronous like Channel.Publish. The error values should still be checked for
|
||||
these methods as they will indicate IO failures like when the underlying
|
||||
connection closes.
|
||||
|
||||
Asynchronous Events
|
||||
|
||||
Clients of this library may be interested in receiving some of the protocol
|
||||
messages other than Deliveries like basic.ack methods while a channel is in
|
||||
confirm mode.
|
||||
|
||||
The Notify* methods with Connection and Channel receivers model the pattern of
|
||||
asynchronous events like closes due to exceptions, or messages that are sent out
|
||||
of band from an RPC call like basic.ack or basic.flow.
|
||||
|
||||
Any asynchronous events, including Deliveries and Publishings must always have
|
||||
a receiver until the corresponding chans are closed. Without asynchronous
|
||||
receivers, the sychronous methods will block.
|
||||
|
||||
Use Case
|
||||
|
||||
It's important as a client to an AMQP topology to ensure the state of the
|
||||
broker matches your expectations. For both publish and consume use cases,
|
||||
make sure you declare the queues, exchanges and bindings you expect to exist
|
||||
prior to calling Channel.Publish or Channel.Consume.
|
||||
|
||||
// Connections start with amqp.Dial() typically from a command line argument
|
||||
// or environment variable.
|
||||
connection, err := amqp.Dial(os.Getenv("AMQP_URL"))
|
||||
|
||||
// To cleanly shutdown by flushing kernel buffers, make sure to close and
|
||||
// wait for the response.
|
||||
defer connection.Close()
|
||||
|
||||
// Most operations happen on a channel. If any error is returned on a
|
||||
// channel, the channel will no longer be valid, throw it away and try with
|
||||
// a different channel. If you use many channels, it's useful for the
|
||||
// server to
|
||||
channel, err := connection.Channel()
|
||||
|
||||
// Declare your topology here, if it doesn't exist, it will be created, if
|
||||
// it existed already and is not what you expect, then that's considered an
|
||||
// error.
|
||||
|
||||
// Use your connection on this topology with either Publish or Consume, or
|
||||
// inspect your queues with QueueInspect. It's unwise to mix Publish and
|
||||
// Consume to let TCP do its job well.
|
||||
|
||||
SSL/TLS - Secure connections
|
||||
|
||||
When Dial encounters an amqps:// scheme, it will use the zero value of a
|
||||
tls.Config. This will only perform server certificate and host verification.
|
||||
|
||||
Use DialTLS when you wish to provide a client certificate (recommended),
|
||||
include a private certificate authority's certificate in the cert chain for
|
||||
server validity, or run insecure by not verifying the server certificate dial
|
||||
your own connection. DialTLS will use the provided tls.Config when it
|
||||
encounters an amqps:// scheme and will dial a plain connection when it
|
||||
encounters an amqp:// scheme.
|
||||
|
||||
SSL/TLS in RabbitMQ is documented here: http://www.rabbitmq.com/ssl.html
|
||||
|
||||
*/
|
||||
package amqp
|
||||
17
vendor/github.com/streadway/amqp/fuzz.go
generated
vendored
17
vendor/github.com/streadway/amqp/fuzz.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
// +build gofuzz
|
||||
|
||||
package amqp
|
||||
|
||||
import "bytes"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
r := reader{bytes.NewReader(data)}
|
||||
frame, err := r.ReadFrame()
|
||||
if err != nil {
|
||||
if frame != nil {
|
||||
panic("frame is not nil")
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
67
vendor/github.com/streadway/amqp/pre-commit
generated
vendored
67
vendor/github.com/streadway/amqp/pre-commit
generated
vendored
@@ -1,67 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
LATEST_STABLE_SUPPORTED_GO_VERSION="1.11"
|
||||
|
||||
main() {
|
||||
if local_go_version_is_latest_stable
|
||||
then
|
||||
run_gofmt
|
||||
run_golint
|
||||
run_govet
|
||||
fi
|
||||
run_unit_tests
|
||||
}
|
||||
|
||||
local_go_version_is_latest_stable() {
|
||||
go version | grep -q $LATEST_STABLE_SUPPORTED_GO_VERSION
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo "$*" 1>&2
|
||||
}
|
||||
|
||||
run_gofmt() {
|
||||
GOFMT_FILES=$(gofmt -l .)
|
||||
if [ -n "$GOFMT_FILES" ]
|
||||
then
|
||||
log_error "gofmt failed for the following files:
|
||||
$GOFMT_FILES
|
||||
|
||||
please run 'gofmt -w .' on your changes before committing."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_golint() {
|
||||
GOLINT_ERRORS=$(golint ./... | grep -v "Id should be")
|
||||
if [ -n "$GOLINT_ERRORS" ]
|
||||
then
|
||||
log_error "golint failed for the following reasons:
|
||||
$GOLINT_ERRORS
|
||||
|
||||
please run 'golint ./...' on your changes before committing."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_govet() {
|
||||
GOVET_ERRORS=$(go tool vet ./*.go 2>&1)
|
||||
if [ -n "$GOVET_ERRORS" ]
|
||||
then
|
||||
log_error "go vet failed for the following reasons:
|
||||
$GOVET_ERRORS
|
||||
|
||||
please run 'go tool vet ./*.go' on your changes before committing."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_unit_tests() {
|
||||
if [ -z "$NOTEST" ]
|
||||
then
|
||||
log_error 'Running short tests...'
|
||||
env AMQP_URL= go test -short
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@@ -401,6 +401,9 @@ github.com/pkg/profile
|
||||
# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
|
||||
## explicit
|
||||
github.com/pmezard/go-difflib/difflib
|
||||
# github.com/rabbitmq/amqp091-go v1.10.0
|
||||
## explicit; go 1.20
|
||||
github.com/rabbitmq/amqp091-go
|
||||
# github.com/rivo/uniseg v0.4.7
|
||||
## explicit; go 1.18
|
||||
github.com/rivo/uniseg
|
||||
@@ -422,9 +425,6 @@ github.com/spf13/pflag
|
||||
# github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf
|
||||
## explicit
|
||||
github.com/ssor/bom
|
||||
# github.com/streadway/amqp v1.1.0
|
||||
## explicit; go 1.10
|
||||
github.com/streadway/amqp
|
||||
# github.com/stretchr/testify v1.9.0
|
||||
## explicit; go 1.17
|
||||
github.com/stretchr/testify/assert
|
||||
|
||||
Reference in New Issue
Block a user