Security News
Weekly Downloads Now Available in npm Package Search Results
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
Oni is a Ruby framework that aims to make it easier to write concurrent daemons using a common code structure. Oni itself does not actually daemonize your code, manage PID files, resources, etc. Instead you should use Oni in combination with other Gems such as daemon-kit.
Oni was built to standardize the structure amongst the different daemon-kit projects used at Olery. As time progressed new structures were used for new daemons and the old ones were often left as is.
Another problem we faced was concurrency. Most daemons were built in a single threaded, single processed manner without an easy place to hook some kind of concurrency model in.
Oni takes care of these problems by providing the following:
Oni assumes developers are somewhat familiar with threading and the potential issues that may arise, it also assumes that your code doesn't leak large amounts of memory over time. Currently there are no plans to include some kind of internal resource management system in Oni, this may change in the future.
To understand the design of Oni we'll first look at the typical work flow of a daemon:
Oni tries to make these kind of workflows by breaking them up into 3 different layers:
Each layer would only do the specific thing it should be doing and would offload other work to the next step in the process. The 3 parts are described in detail below.
The daemon layer spawns a number of threads that will each receive and perform work separately. Typically these workers are long running tasks that poll some kind of message queue for jobs to process.
In initial iterations Oni used a main job dispatcher (running in the main thread) and a separate thread pool for the workers. This proved problematic with message queue setups as it would result in the main thread pulling in all available jobs and then internally queing them again given there weren't enough workers available. This would mean that if the process would crash the messages were lost. As a result of this each worker is started in it's own separate thread.
Comparing Oni with other framework structures one could see the daemon layer as a controller (in MVC frameworks), it merely dispatches work to the mapper and worker instead of doing everything itself.
The mapper is tasked with two things:
The input transformation is put in place to ensure that workers only get data that they actually need instead of just receiving the raw message (which may include all kinds of meta data completely useless to a worker). It also ensures that the input is actually correct before ever passing it to a worker.
A typical thing at Olery is that a job gets scheduled and has to pass through multiple steps (= daemons) before being completed. Some of these daemons would add extra meta-data to the message (e.g. batch IDs, timings, etc) but these aren't strictly required to perform an actual job, thus there's no need to pass it around several layers deep into your codebase.
In the above case the mapper would take care of validating/scrubbing the input and adding extra meta-data to the output.
The worker would perform the actual work and return some kind of output to the daemon. Oni assumes that workers behave reasonably well, currently there's no mechanism in place to deal with memory leaks and the likes. Oni also assumes that developers are somewhat capable of dealing with asynchronous code since all work is performed asynchronously outside of the daemon layer.
Install the Gem:
gem install oni
Basic usage of Oni is as following:
require 'oni'
# This example defines 3 classes: MyDaemon, MyMapper and MyWorker.
# Combined they form the basic structure of an Oni Daemon.
class MyDaemon < Oni::Daemon
set :mapper, MyMapper
set :worker, MyWorker
# Here you'd receive your message, e.g. from a queue. We'll use static
# data as an example.
def receive
yield({:number => 10})
end
# This would get executed upon completion of a job.
def complete(message, result)
puts result
end
end
class MyMapper < Oni::Mapper
# Map the input given by MyDaemon#receive into the right arguments
# for MyWorker#initialize.
#
# NOTE: the return value should be an Array.
# Oni calls #to_a on the output (more specifically we use a splat) so your
# return value should be an Array. If you do not return an Array you risk
# that the object you return will wrongfully be converted into an Array.
# This is painful when it comes to Hashes, which, after the #to_a call
# will be converted into arrays of values in stead of your intended hash.
def map_input(input)
return [input[:number]]
end
def map_output(output)
return {:number => output, :completed => Time.now}
end
end
class MyWorker < Oni::Worker
def initialize(number)
@number = number
end
def process
return @number * 2
end
end
The source code of this repository and Oni itself are licensed under the MIT license unless specified otherwise. A copy of this license can be found in the file "LICENSE" in the root directory of this repository.
FAQs
Unknown package
We found that oni demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.
Security News
A Stanford study reveals 9.5% of engineers contribute almost nothing, costing tech $90B annually, with remote work fueling the rise of "ghost engineers."
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.