Re-arrange for nimble, update to Nim 0.19.
This commit is contained in:
parent
14eff18d54
commit
b06edfff88
4 changed files with 63 additions and 44 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
syntax: glob
|
||||||
.cache
|
.cache
|
||||||
stomp$
|
stomp
|
||||||
stomp.html
|
src/stomp
|
||||||
|
*.html
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -1,11 +1,12 @@
|
||||||
|
|
||||||
FILES = stomp.nim
|
FILES = src/stomp.nim
|
||||||
CACHE = .cache
|
CACHE = .cache
|
||||||
|
|
||||||
default: development
|
default: development
|
||||||
|
|
||||||
development: ${FILES}
|
development: ${FILES}
|
||||||
nim --debugInfo --assertions:on --linedir:on -d:ssl --define:debug --nimcache:${CACHE} c ${FILES}
|
nim --debugInfo --assertions:on --linedir:on -d:ssl --define:debug --nimcache:${CACHE} c ${FILES}
|
||||||
|
@mv src/stomp .
|
||||||
|
|
||||||
autobuild:
|
autobuild:
|
||||||
# find . -depth 1 -name \*.nim | entr -cp make
|
# find . -depth 1 -name \*.nim | entr -cp make
|
||||||
|
|
@ -16,6 +17,7 @@ debugger: ${FILES}
|
||||||
|
|
||||||
release: ${FILES}
|
release: ${FILES}
|
||||||
nim -d:release --opt:speed --nimcache:${CACHE} c ${FILES}
|
nim -d:release --opt:speed --nimcache:${CACHE} c ${FILES}
|
||||||
|
@mv src/stomp .
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
nim doc ${FILES}
|
nim doc ${FILES}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# vim: set et nosta sw=4 ts=4 ft=nim :
|
# vim: set et nosta sw=4 ts=4 ft=nim :
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016, Mahlon E. Smith <mahlon@martini.nu>
|
# Copyright (c) 2016-2018, Mahlon E. Smith <mahlon@martini.nu>
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
# modification, are permitted provided that the following conditions are met:
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
|
@ -48,16 +48,6 @@
|
||||||
## This library has been tested with recent versions of RabbitMQ. If it
|
## This library has been tested with recent versions of RabbitMQ. If it
|
||||||
## works for you with another broker, please let the author know.
|
## works for you with another broker, please let the author know.
|
||||||
##
|
##
|
||||||
##
|
|
||||||
## Protocol support
|
|
||||||
## ----------------
|
|
||||||
##
|
|
||||||
## Examples
|
|
||||||
## =========
|
|
||||||
##
|
|
||||||
## Connecting with SSL
|
|
||||||
## -------------------
|
|
||||||
##
|
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils,
|
strutils,
|
||||||
|
|
@ -68,7 +58,7 @@ import
|
||||||
uri
|
uri
|
||||||
|
|
||||||
const
|
const
|
||||||
VERSION = "0.1.0" ## The current program version.
|
VERSION = "0.1.1" ## The current program version.
|
||||||
NULL = "\x00" ## The NULL character.
|
NULL = "\x00" ## The NULL character.
|
||||||
CR = "\r" ## The carriage return character.
|
CR = "\r" ## The carriage return character.
|
||||||
CRLF = "\r\n" ## Carriage return + Line feed (EOL).
|
CRLF = "\r\n" ## Carriage return + Line feed (EOL).
|
||||||
|
|
@ -218,7 +208,7 @@ proc newStompResponse( c: StompClient ): StompResponse =
|
||||||
#
|
#
|
||||||
if result.payload.len > 0:
|
if result.payload.len > 0:
|
||||||
if result.payload == NULL: # We checked for a body, but there was none.
|
if result.payload == NULL: # We checked for a body, but there was none.
|
||||||
result.payload = nil
|
result.payload = ""
|
||||||
if defined( debug ): printf " <--\n <-- ^@\n\n"
|
if defined( debug ): printf " <--\n <-- ^@\n\n"
|
||||||
else:
|
else:
|
||||||
if defined( debug ): printf " <--\n <-- (payload)^@\n\n"
|
if defined( debug ): printf " <--\n <-- (payload)^@\n\n"
|
||||||
|
|
@ -240,7 +230,7 @@ proc `[]`*( response: StompResponse, key: string ): string =
|
||||||
for header in response.headers:
|
for header in response.headers:
|
||||||
if cmpIgnoreCase( key, header.name ) == 0:
|
if cmpIgnoreCase( key, header.name ) == 0:
|
||||||
return header.value
|
return header.value
|
||||||
return nil
|
return ""
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
|
|
@ -349,19 +339,18 @@ proc finmsg( c: StompClient ): void =
|
||||||
|
|
||||||
proc `[]`*( c: StompClient, key: string ): string =
|
proc `[]`*( c: StompClient, key: string ): string =
|
||||||
## Get a specific value from the server metadata, set during the initial connection.
|
## Get a specific value from the server metadata, set during the initial connection.
|
||||||
if not c.connected: return nil
|
if not c.connected: return ""
|
||||||
for header in c.serverinfo:
|
for header in c.serverinfo:
|
||||||
if cmpIgnoreCase( key, header.name ) == 0:
|
if cmpIgnoreCase( key, header.name ) == 0:
|
||||||
return header.value
|
return header.value
|
||||||
return nil
|
return ""
|
||||||
|
|
||||||
|
|
||||||
proc `$`*( c: StompClient ): string =
|
proc `$`*( c: StompClient ): string =
|
||||||
## Represent the stomp client as a string, after masking the password.
|
## Represent the stomp client as a string, after masking the password.
|
||||||
let uri = ( $c.uri ).replace( ":" & c.uri.password & "@", "@" )
|
let uri = ( $c.uri ).replace( ":" & c.uri.password & "@", "@" )
|
||||||
result = "(NimStomp v" & VERSION & ( if c.connected: " connected" else: " not connected" ) & " to " & uri
|
result = "(NimStomp v" & VERSION & ( if c.connected: " connected" else: " not connected" ) & " to " & uri
|
||||||
if not c[ "server" ].is_nil:
|
if not ( c[ "server" ] == "" ): result.add( " --> " & c["server"] )
|
||||||
result.add( " --> " & c["server"] )
|
|
||||||
result.add( ")" )
|
result.add( ")" )
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -428,8 +417,8 @@ proc add_txn( c: StompClient ): void =
|
||||||
|
|
||||||
proc send*( c: StompClient,
|
proc send*( c: StompClient,
|
||||||
destination: string,
|
destination: string,
|
||||||
message: string = nil,
|
message: string = "",
|
||||||
contenttype: string = nil,
|
contenttype: string = "",
|
||||||
headers: seq[ tuple[name: string, value: string] ] = @[] ): void =
|
headers: seq[ tuple[name: string, value: string] ] = @[] ): void =
|
||||||
## Send a **message** to **destination**.
|
## Send a **message** to **destination**.
|
||||||
##
|
##
|
||||||
|
|
@ -445,7 +434,7 @@ proc send*( c: StompClient,
|
||||||
c.socksend( "SEND" & CRLF )
|
c.socksend( "SEND" & CRLF )
|
||||||
c.socksend( "destination:" & destination & CRLF )
|
c.socksend( "destination:" & destination & CRLF )
|
||||||
c.socksend( "content-length:" & $message.len & CRLF )
|
c.socksend( "content-length:" & $message.len & CRLF )
|
||||||
if not contenttype.is_nil: c.socksend( "content-type:" & contenttype & CRLF )
|
if not ( contenttype == "" ): c.socksend( "content-type:" & contenttype & CRLF )
|
||||||
|
|
||||||
# Add custom headers. Add transaction header if one isn't manually
|
# Add custom headers. Add transaction header if one isn't manually
|
||||||
# present (and a transaction is open.)
|
# present (and a transaction is open.)
|
||||||
|
|
@ -456,7 +445,7 @@ proc send*( c: StompClient,
|
||||||
c.socksend( header.name & ":" & header.value & CRLF )
|
c.socksend( header.name & ":" & header.value & CRLF )
|
||||||
if not txn_seen: c.add_txn
|
if not txn_seen: c.add_txn
|
||||||
|
|
||||||
if message.is_nil:
|
if message == "":
|
||||||
c.finmsg
|
c.finmsg
|
||||||
else:
|
else:
|
||||||
c.socket.send( CRLF & message & NULL )
|
c.socket.send( CRLF & message & NULL )
|
||||||
|
|
@ -526,11 +515,11 @@ proc begin*( c: StompClient, txn: string ): void =
|
||||||
c.transactions.add( txn )
|
c.transactions.add( txn )
|
||||||
|
|
||||||
|
|
||||||
proc commit*( c: StompClient, txn: string = nil ): void =
|
proc commit*( c: StompClient, txn: string = "" ): void =
|
||||||
## Finish a specific transaction **txn**, or the most current if unspecified.
|
## Finish a specific transaction **txn**, or the most current if unspecified.
|
||||||
var transaction = txn
|
var transaction = txn
|
||||||
if transaction.is_nil and c.transactions.len > 0: transaction = c.transactions.pop
|
if transaction == "" and c.transactions.len > 0: transaction = c.transactions.pop
|
||||||
if transaction.is_nil: return
|
if transaction == "": return
|
||||||
|
|
||||||
c.socksend( "COMMIT" & CRLF )
|
c.socksend( "COMMIT" & CRLF )
|
||||||
c.socksend( "transaction:" & transaction & CRLF )
|
c.socksend( "transaction:" & transaction & CRLF )
|
||||||
|
|
@ -544,11 +533,11 @@ proc commit*( c: StompClient, txn: string = nil ): void =
|
||||||
c.transactions = new_transactions
|
c.transactions = new_transactions
|
||||||
|
|
||||||
|
|
||||||
proc abort*( c: StompClient, txn: string = nil ): void =
|
proc abort*( c: StompClient, txn: string = "" ): void =
|
||||||
## Cancel a specific transaction **txn**, or the most current if unspecified.
|
## Cancel a specific transaction **txn**, or the most current if unspecified.
|
||||||
var transaction = txn
|
var transaction = txn
|
||||||
if transaction.is_nil and c.transactions.len > 0: transaction = c.transactions.pop
|
if transaction == "" and c.transactions.len > 0: transaction = c.transactions.pop
|
||||||
if transaction.is_nil: return
|
if transaction == "": return
|
||||||
|
|
||||||
c.socksend( "ABORT" & CRLF )
|
c.socksend( "ABORT" & CRLF )
|
||||||
c.socksend( "transaction:" & transaction & CRLF )
|
c.socksend( "transaction:" & transaction & CRLF )
|
||||||
|
|
@ -562,20 +551,20 @@ proc abort*( c: StompClient, txn: string = nil ): void =
|
||||||
c.transactions = new_transactions
|
c.transactions = new_transactions
|
||||||
|
|
||||||
|
|
||||||
proc ack*( c: StompClient, id: string, transaction: string = nil ): void =
|
proc ack*( c: StompClient, id: string, transaction: string = "" ): void =
|
||||||
## Acknowledge message **id**. Optionally, attach this acknowledgement
|
## Acknowledge message **id**. Optionally, attach this acknowledgement
|
||||||
## to a specific **transaction** -- if there's only one active, it is
|
## to a specific **transaction** -- if there's only one active, it is
|
||||||
## added automatically.
|
## added automatically.
|
||||||
c.socksend( "ACK" & CRLF )
|
c.socksend( "ACK" & CRLF )
|
||||||
c.socksend( "id:" & id & CRLF )
|
c.socksend( "id:" & id & CRLF )
|
||||||
if not transaction.is_nil:
|
if not ( transaction == "" ):
|
||||||
c.socksend( "transaction:" & transaction & CRLF )
|
c.socksend( "transaction:" & transaction & CRLF )
|
||||||
else:
|
else:
|
||||||
c.add_txn
|
c.add_txn
|
||||||
c.finmsg
|
c.finmsg
|
||||||
|
|
||||||
|
|
||||||
proc nack*( c: StompClient, id: string, transaction: string = nil ): void =
|
proc nack*( c: StompClient, id: string, transaction: string = "" ): void =
|
||||||
## Reject message **id**. Optionally, attach this rejection to a
|
## Reject message **id**. Optionally, attach this rejection to a
|
||||||
## specific **transaction** -- if there's only one active, it is
|
## specific **transaction** -- if there's only one active, it is
|
||||||
## added automatically.
|
## added automatically.
|
||||||
|
|
@ -591,7 +580,7 @@ proc nack*( c: StompClient, id: string, transaction: string = nil ): void =
|
||||||
##
|
##
|
||||||
c.socksend( "NACK" & CRLF )
|
c.socksend( "NACK" & CRLF )
|
||||||
c.socksend( "id:" & id & CRLF )
|
c.socksend( "id:" & id & CRLF )
|
||||||
if not transaction.is_nil:
|
if not ( transaction == "" ):
|
||||||
c.socksend( "transaction:" & transaction & CRLF )
|
c.socksend( "transaction:" & transaction & CRLF )
|
||||||
else:
|
else:
|
||||||
c.add_txn
|
c.add_txn
|
||||||
|
|
@ -618,7 +607,7 @@ proc wait_for_messages*( c: StompClient, loop=true ) =
|
||||||
else:
|
else:
|
||||||
timeout = -1
|
timeout = -1
|
||||||
|
|
||||||
if select( fds, timeout ) == 0: # timeout, only happens if heartbeating missed
|
if select_read( fds, timeout ) == 0: # timeout, only happens if heartbeating missed
|
||||||
if not isNil( c.missed_heartbeat_callback ):
|
if not isNil( c.missed_heartbeat_callback ):
|
||||||
c.missed_heartbeat_callback( c )
|
c.missed_heartbeat_callback( c )
|
||||||
else:
|
else:
|
||||||
|
|
@ -688,7 +677,29 @@ when isMainModule:
|
||||||
socket = newSocket()
|
socket = newSocket()
|
||||||
messages: seq[ StompResponse ] = @[]
|
messages: seq[ StompResponse ] = @[]
|
||||||
|
|
||||||
if paramCount() != 3: quit "See source comments for how to run functional tests."
|
let usage = """
|
||||||
|
First start up a message receiver:
|
||||||
|
./stomp receiver [stomp-uri] [subscription-destination]
|
||||||
|
|
||||||
|
then run another process, to publish stuff:
|
||||||
|
./stomp publisher [stomp-uri] [publish-destination]
|
||||||
|
|
||||||
|
An example with an AMQP "direct" exchange, and an exclusive queue:
|
||||||
|
./stomp publisher stomp://test:test@localhost/?heartbeat=10 /exchange/test
|
||||||
|
./stomp receiver stomp://test:test@localhost/?heartbeat=10 /exchange/test
|
||||||
|
|
||||||
|
Then just let 'er run.
|
||||||
|
|
||||||
|
You can also run a nieve benchmark (deliveries/sec):
|
||||||
|
|
||||||
|
./stomp benchmark stomp://test:test@localhost/ /exchange/test
|
||||||
|
|
||||||
|
It will set messages to require acknowledgement, and nack everything, causing
|
||||||
|
a delivery loop for 10 seconds.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
if paramCount() != 3: quit usage
|
||||||
|
|
||||||
var stomp = newStompClient( socket, paramStr(2) )
|
var stomp = newStompClient( socket, paramStr(2) )
|
||||||
stomp.connect
|
stomp.connect
|
||||||
|
|
@ -709,7 +720,7 @@ when isMainModule:
|
||||||
stomp.message_callback = incr
|
stomp.message_callback = incr
|
||||||
stomp.subscribe( paramStr(3), "client" )
|
stomp.subscribe( paramStr(3), "client" )
|
||||||
stomp.send( paramStr(3), "hi." )
|
stomp.send( paramStr(3), "hi." )
|
||||||
while get_time() - start < 10:
|
while get_time() < start + 10.seconds:
|
||||||
stomp.wait_for_messages( false )
|
stomp.wait_for_messages( false )
|
||||||
|
|
||||||
printf "* Processed %d messages in 10 seconds.\n", count
|
printf "* Processed %d messages in 10 seconds.\n", count
|
||||||
|
|
@ -745,7 +756,7 @@ when isMainModule:
|
||||||
# Assertions on the results!
|
# Assertions on the results!
|
||||||
#
|
#
|
||||||
doAssert( messages.len == expected )
|
doAssert( messages.len == expected )
|
||||||
doAssert( messages[0].payload == nil )
|
doAssert( messages[0].payload == "" )
|
||||||
|
|
||||||
doAssert( messages[1].payload == "Hello world!" )
|
doAssert( messages[1].payload == "Hello world!" )
|
||||||
|
|
||||||
|
|
@ -829,7 +840,7 @@ when isMainModule:
|
||||||
headers = @[]
|
headers = @[]
|
||||||
headers.add( ("transaction", "test-" & $i ) )
|
headers.add( ("transaction", "test-" & $i ) )
|
||||||
stomp.begin( "test-" & $i )
|
stomp.begin( "test-" & $i )
|
||||||
stomp.send( paramStr(3), "transaction " & $i, nil, headers )
|
stomp.send( paramStr(3), "transaction " & $i, "", headers )
|
||||||
sleep 500
|
sleep 500
|
||||||
stomp.abort( "test-1" )
|
stomp.abort( "test-1" )
|
||||||
sleep 500
|
sleep 500
|
||||||
|
|
@ -842,6 +853,5 @@ when isMainModule:
|
||||||
echo "* Tests passed!"
|
echo "* Tests passed!"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
quit "See source comments for how to run functional tests."
|
quit usage
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
|
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
author = "Mahlon E. Smith <mahlon@martini.nu>"
|
author = "Mahlon E. Smith <mahlon@martini.nu>"
|
||||||
description = "A pure-nim implementation of the STOMP protocol for machine messaging."
|
description = "A pure-nim implementation of the STOMP protocol for machine messaging."
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
installExt = @["stomp"]
|
||||||
|
bin = @["stomp"]
|
||||||
|
srcDir = "src"
|
||||||
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
requires "nim >= 0.13.0"
|
requires "nim >= 0.19.0"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue