Skip to content

Commit

Permalink
Add non-blocking channel
Browse files Browse the repository at this point in the history
  • Loading branch information
creadone committed Mar 1, 2021
1 parent c409078 commit 74d0226
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 48 deletions.
43 changes: 30 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,46 @@ dependencies:
## Usage

```crystal
require "json"
require "cocoon"
require "http/client"
alias Response = HTTP::Client::Response
cocoon = Cocoon::Wrapper(Response).new
channel = cocoon.wrap do
headers = HTTP::Headers{ "Accept" => "application/vnd.github.v3+json" }
HTTP::Client.get "https://api.github.com/networks/crystal-lang/crystal/events", headers: headers
end
if resp = channel.receive
if resp.is_a?(Response)
if resp.success?
pp Array(Hash(String, JSON::Any)).from_json(resp.body)
loop do
result = cocoon.wrap do
if Random.rand > 0.5
HTTP::Client.get("https://github.com")
else
Log.warn{ HTTP::Status.new(resp.status_code).description }
raise "Connection is lost"
end
elsif resp.is_a?(Exception)
Log.warn exception: resp, &.emit("Hi dear! I missed you.")
end
# something in the &block raised Exception
if result.is_a?(Exception)
puts result.message
end
# &block is done
if result.is_a?(Response)
puts "X-GitHub-Request-Id: #{result.headers["X-GitHub-Request-Id"]}"
end
# &block has no result or task is not ended yet
if result.is_a?(Nil)
puts "Nothing..."
end
sleep 1
end
# => Nothing...
# => X-GitHub-Request-Id: EF51:10C35:3A33E0D:3BCCF8A:603C72E7
# => Connection is lost
# => X-GitHub-Request-Id: EF52:0AF5:44114C4:45B5044:603C72E9
# => X-GitHub-Request-Id: EF53:E298:B55ADC:B9B0DF:603C72EA
# => Connection is lost
# => Connection is lost
```

## Contributing
Expand Down
24 changes: 0 additions & 24 deletions example/base.cr

This file was deleted.

32 changes: 32 additions & 0 deletions sample/base.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require "cocoon"
require "http/client"

alias Response = HTTP::Client::Response
cocoon = Cocoon::Wrapper(Response).new

loop do
result = cocoon.wrap do
if Random.rand > 0.5
HTTP::Client.get("https://github.com")
else
raise "Connection is lost"
end
end

# something in the &block raised Exception
if result.is_a?(Exception)
puts result.message
end

# &block is done
if result.is_a?(Response)
puts "X-GitHub-Request-Id: #{result.headers["X-GitHub-Request-Id"]}"
end

# &block has no result or task is not ended yet
if result.is_a?(Nil)
puts "Nothing..."
end

sleep 1
end
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: cocoon
version: 0.1.3
version: 0.2.3

authors:
- Sergey Fedorov <creadone@gmail.com>
Expand Down
2 changes: 1 addition & 1 deletion spec/cocoon_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe Cocoon do
cocoon = Cocoon::Wrapper(Int32).new

it "should return sum of integers" do
if result = cocoon.wrap{ 1 + 3 }.receive
if result = cocoon.wrap { 1 + 3 }
result.should eq(4)
end
end
Expand Down
20 changes: 11 additions & 9 deletions src/cocoon.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,30 @@ module Cocoon

class Wrapper(T)
def initialize(
@result = Channel(T | Exception).new,
@output = Channel(T | Exception).new
@result = Channel(T | Exception | Nil).new,
@output = Channel(T | Exception | Nil).new
)
end

def wrap(&block : -> T) forall T
spawn(name: "executor") do
if data = block.call
@result.send data
end
rescue ex
@result.send ex
data = block.call
@result.send data
rescue ex
@result.send ex
end

Fiber.yield

spawn(name: "receiver") do
if data = @result.receive
select
when data = @result.receive
@output.send data
else
@output.send nil
end
end
@output
@output.receive
end
end
end

0 comments on commit 74d0226

Please sign in to comment.