Skip to content

Repository files navigation

SmartCore::Engine · Supported by Cado Labs · Gem Version

Generic SmartCore functionality.


Supported by Cado Labs


Installation

gem'smart_engine'
bundle install
# --- or ---
gem install smart_engine
require'smart_core'

Technologies


Global set of error types

  • SmartCore::Error (inherited from ::StandardError);
  • SmartCore::ArgumentError (inherited from ::ArgumentError);
  • SmartCore::FrozenError (inherited from ::FrozenError);
  • SmartCore::NameError (inherited from ::NameError);
  • SmartCore::TypeError (inherited from ::TypeError);

Simple reentrant lock

lock=SmartCore::Engine::Lock.newlock.synchronize{your_code}

Read/Write Lock

  • non-controlable reader count;
  • readers does not lock each other;
  • readers waits for writer;
  • writer waits for readers;
lock=SmartCore::Engine::ReadWriteLock.newlock.read_sync{ ...some-read-op... }# waits for writerlock.read_sync{ ...some-read-op... }# waits for writerlock.write_sync{ ... some-write-op... }# waits for all readers and current writer# is write_sync lock is owned by current thread?lock.write_owned?# true or false

Cache Storage

  • you can use any object as a cache key;

  • you can store any object as a cache value;

  • you can cache nil object too;

  • cache read has fetch semantics:

    • signature: #read(key, &fallback);
    • in the event of cache miss the &fallback black will be invoked;
    • the return value of the fallback block will be written to the cache, and that return value will be returned;
  • cache write:

    • signature: #write(key, value);
    • you can use any object as a cache key;
    • you can store any object as a value;
    • you can write nil object too;
  • cache clear:

    • signature: #clear;
cache=SmartCore::Engine::Cache.new# write and readcache.write(:amount,123.456)# => 123.456cache.read(:amount)# => 123.456# read non-existing with a fallbackcache.read('name')# => nilcache.read('name'){'D@iVeR'}# => 'D@iVeR'cache.read('name')# => 'D@iVeR'# store nil objectcache.write(:nil_value,nil)# => nilcache.read(:nil_value)# => nilcache.read(:nil_value){'rewritten'}# => nilcache.read(:nil_value)# => nil# clear cachecache.clear# => nil
# aliases:# write:cache[:key1]='test'# read:cache[:key1]# => 'test'# read with fallback:cache[:key2]{'test2'}# => 'test2'cache[:key2]# => 'test2'

Atomic thread-safe value container

atom=SmartCore::Engine::Atom.new# initial value - nilatom.value# => nil# --- or ---atom=SmartCore::Engine::Atom.new(7)# initial value - 7atom.value# => 7# set new value (thread-safely)atom.swap{ |original_value| original_value * 2}atom.value# => 14

Any Object Frozener

  • works with any type of ruby objects (event with BasicObject);
  • uses classic Ruby C-level frozen?/freeze functionality;
# as a singletonobject=BasicObject.newSmartCore::Engine::Frozener.frozen?(object)# => falseSmartCore::Engine::Frozener.freeze(object)SmartCore::Engine::Frozener.frozen?(object)# => true
# as a mixinclassEmptyObject < BasicObjectincludeSmartCore::Engine::Frozener::Mixinendobject=EmptyObject.newobject.frozen?# => falseobject.freezeobject.frozen?# => true

Basic Object Refinements

Ruby's BasicObject class does not have some fundamental (extremely important for instrumenting) methods:

  • is_a? / kind_of?
  • instance_of?
  • freeze / frozen?
  • hash
  • nil?
  • inspect

SmartCore::Ext::BasicObjectAsObject refinement solves this problem (by Ruby's internal API without any manualy-emulated behavior).

# without refinement:basic_obj= ::BasicObject.newbasic_obj.is_a?(::BasicObject)# raises ::NoMethodErrorbasic_obj.kind_of?(::BasicObject)# raises ::NoMethodErrorbasic_obj.instance_of?(::BasicObject)# rasies ::NoMethodErrorbasic_obj.freeze# raises ::NoMethodErrorbasic_obj.frozen?# raises ::NoMethodErrorbasic_object.hash# raises ::NoMethodErrorbasic_object.nil?# raises ::NoMethodErrorbasic_object.inspect# raises ::NoMethodError
# with refinement:usingSmartCore::Ext::BasicObjectAsObjectbasic_obj= ::BasicObject.newbasic_obj.is_a?(::BasicObject)# => truebasic_obj.kind_of?(::BasicObject)# => truebasic_obj.instance_of?(::BasicObject)# => truebasic_obj.instance_of?(::Object)# => falsebasic_obj.is_a?(::Integer)# => falsebasic_obj.kind_of?(::Integer)# => falsebasic_obj.frozen?# => falsebasic_obj.freeze# => selfbasic_obj.frozen?# => truebasic_obj.nil?# => falsebasic_obj.hash# => 2682859680348634421 (some Integer value)basic_obj.inspect# => "#<BasicObject:0x00007fe428018628>"

Inline rescue pipe

  • works with an array of proc objects;
  • returns the result of the first non-failed proc;
  • provides an error interception interface (a block argument);
  • fails with the last failed proc exception (if all procs were failed and interceptor was not passed);

Return the result of the first non-failed proc

SmartCore::Engine::RescueExt.inline_rescue_pipe(->{raise},->{raise},->{123},->{567},->{raise},)# => output: 123

Fail with the last failed proc exception

SmartCore::Engine::RescueExt.inline_rescue_pipe(->{raise(::ArgumentError)},->{raise(::TypeError)},->{raise(::ZeroDivisionError)})# => fails with ZeroDivisionError

Error interception

SmartCore::Engine::RescueExt.inline_rescue_pipe(->{raise(::ArgumentError)},->{raise(::TypeError)},->{raise(::ZeroDivisionError,'Intercepted exception')})do |error|
error.messageend# => output: "Intercepted exception"

Roadmap

  • migrate to Github Actions in CI;
  • thread-safety for BasicObject extensions;
  • SmartCore::Engine::Cache:
    • thread-safety;
    • support for ttl: option for #write and for fallback block attribute of #read;
    • support for key-value-pair iteration;
    • support for #keys method;
    • support for #key? method;
    • think about some layer of cache object serialization;
  • SmartCore::Engine::ReadWriteLock:
    • an ability to set a maximum count of readers;

Contributing

  • Fork it ( https://github.com/smart-rb/smart_engine )
  • Create your feature branch (git checkout -b feature/my-new-feature)
  • Commit your changes (git commit -am '[feature_context] Add some feature')
  • Push to the branch (git push origin feature/my-new-feature)
  • Create new Pull Request

License

Released under MIT License.

Supporting

Supported by Cado Labs

Authors

Rustam Ibragimov

About

Generic SmartCore functionality.

Topics

Resources

Code of conduct

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages