Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
erdnaxeli committed Dec 12, 2020
0 parents commit 47aba2f
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*.cr]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/docs/
/lib/
/bin/
/.shards/
*.dwarf

# Libraries don't need dependency lock
# Dependencies will be locked in applications that use them
/shard.lock
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: crystal

# Uncomment the following if you'd like Travis to run specs and check code formatting
# script:
# - crystal spec
# - crystal tool format --check
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2020 your-name-here

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
all:
shards build --release

doc:
crystal doc

init-dev:
shards install

lint:
crystal tool format
./bin/ameba src spec

test:
crystal spec --error-trace

.PHONY: test
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# marmot

Marmot is a scheduler, use it to schedule tasks.

## Installation

1. Add the dependency to your `shard.yml`:

```yaml
dependencies:
marmot:
github: erdnaxeli/marmot
```

2. Run `shards install`

## Usage

```crystal
require "marmot"
repetitions
# This task will repeat every 15 minutes.
repeat_task = Marmot.repeat(15.minutes) { puts Time.local }
# This task will run every day at 15:28:43, and will cancel the previous task.
Marmot.cron(hour: 15, minute: 28, second: 43) do
puts "It is 15:28:43: #{Time.local}"
repeat_task.cancel
end
times = 0
# This task will run every 10 seconds and will cancel itself after 10 runs.
Marmot.repeat(10.seconds) do |task|
times += 1
puts "#{times} times"
task.cancel if times = 10
end
# Start the scheduler.
Marmot.run
```

## Development

Don't forget to run the test.

As they deal with timing, they could fail if your computer is busy.
Do not hesitate to run then many times if that happens.

## Contributing

1. Fork it (<https://github.com/erdnaxeli/marmot/fork>)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request

## Contributors

- [erdnaxeli](https://github.com/erdnaxeli) - creator and maintainer
14 changes: 14 additions & 0 deletions shard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: marmot
version: 0.1.0

authors:
- Alexandre Morignot <erdnaxeli@cervoi.se>

crystal: 0.35.1

license: MIT

development_dependencies:
ameba:
github: crystal-ameba/ameba
version: ~>0.13.2
163 changes: 163 additions & 0 deletions spec/marmot_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
require "./spec_helper"

def expect_channel_eq(channel, value)
select
when x = channel.receive
x.should eq(value)
else
raise "A value was expected"
end
end

def expect_channel_be(channel, value)
select
when x = channel.receive
x.should be(value)
else
raise "A value was expected"
end
end

describe Marmot do
describe "#repeat" do
it "schedules a new task that repeats" do
channel = Channel(Int32).new

x = 0
task = Marmot.repeat(10.milliseconds) do
x += 1
channel.send(x)
end
spawn Marmot.run

sleep 15.milliseconds
expect_channel_eq(channel, 1)
sleep 10.milliseconds
expect_channel_eq(channel, 2)
sleep 10.milliseconds
expect_channel_eq(channel, 3)

task.cancel
channel.close
Marmot.stop
end

it "runs on first run if specified" do
channel = Channel(Int32).new

x = 0
task = Marmot.repeat(10.milliseconds, true) do
x += 1
channel.send(x)
end
spawn Marmot.run

sleep 5.milliseconds
expect_channel_eq(channel, 1)

task.cancel
channel.close
Marmot.stop
end
end

describe "#cron" do
it "schedules a new task" do
channel = Channel(Int32).new

time = Time.local.at_beginning_of_second + 2.second
task = Marmot.cron(time.hour, time.minute, time.second) { channel.send(1) }
spawn Marmot.run

sleep (time - Time.local + 5.milliseconds)
expect_channel_eq(channel, 1)

task.cancel
channel.close
Marmot.stop
end
end

describe "#run" do
it "runs a task without arguments" do
channel = Channel(Int32).new

task = Marmot.repeat(3.milliseconds) { channel.send(1) }
spawn Marmot.run

sleep 5.milliseconds
expect_channel_eq(channel, 1)

task.cancel
channel.close
Marmot.stop
end

it "runs a task with one argument and gives it its Task object" do
channel = Channel(Marmot::Task).new

task = Marmot.repeat(3.milliseconds) { |t| channel.send(t) }
spawn Marmot.run

sleep 5.milliseconds
expect_channel_be(channel, task)

task.cancel
channel.close
Marmot.stop
end

it "stops canceled tasks" do
channel = Channel(Marmot::Task).new

task = Marmot.repeat(3.milliseconds) do |t|
t.cancel
channel.close
end
spawn Marmot.run

sleep 5.milliseconds
channel.closed?.should be_true
task.canceled?.should be_true

Marmot.stop
end

it "does not run when there is no tasks" do
channel = Channel(Int32).new

task = Marmot.repeat(1.milliseconds) { }
task.cancel

spawn do
Marmot.run
channel.send(1)
end

Fiber.yield
expect_channel_eq(channel, 1)
channel.close
end
end

describe "#stop" do
it "stops the tasks but does not cancel them" do
channel = Channel(Int32).new

task = Marmot.repeat(10.milliseconds) { channel.send(1) }
spawn do
Marmot.run
channel.send(2)
end

sleep 15.milliseconds
expect_channel_eq(channel, 1)

Marmot.stop
Fiber.yield
expect_channel_eq(channel, 2)

task.canceled?.should be_false
end
end
end
2 changes: 2 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require "spec"
require "../src/marmot"
Loading

0 comments on commit 47aba2f

Please sign in to comment.