Skip to content

Latest commit

 

History

History
829 lines (532 loc) · 18.5 KB

BACKLOG.md

File metadata and controls

829 lines (532 loc) · 18.5 KB

Backlog

*Priority levels: Low, Medium, High, Critical, Unknown.

*Complexity levels: Easy, Moderate, Hard, Extreme, Unknown.

*Different naming conventions for priority and complexity are used intentionally to simplify task lookup.


Docs

Write comprehensive user docs

Priority Complexity Status Tags
Medium High TODO docs, user-docs

Describe every available Conveninet Service feature at least once.

Notes:


Add YARD type signatures for the whole codebase

Priority Complexity Status Tags
Medium Easy TODO yard, yard-tags, api-docs

Ensure YARD type signatures are properly rendered in the Convenient Service API docs.

Notes:


Show an example of id_or_record attribute

Priority Complexity Status Tags
Low Easy TODO id-or-record, attributes

Notes:


Promotion

Add Convenient Service to the Ruby Toolbox Catalogue

Once the first major version is released, add Convenient Service to the Ruby Toolbox Catalogue.

Open a PR that modifies the following file.


Features

Introduce stub_entry RSpec matcher

Priority Complexity Status Tags
High Medium TODO stub-entry, rspec-matcher
stub_entry(SomeFeature, :some_entry)
  .with_arguments(*args, **kwargs, &block)
  .to return_value(:some_value)

Shorter syntax for inputs without options.

Priority Complexity Status Tags
Medium Easy TODO inputs, short-syntax
# before
step SuccessService,
  in: [
    {nesting_level: raw(nesting_level)},
    {index: index}
  ],
  out: :id

# after
step SuccessService,
  in: {
    nesting_level: raw(nesting_level),
    index: index
  },
  out: :id

Notes:

  • This is a crucial task before the v1.0.0 release.

Introduce the include_config RSpec matcher.

Priority Complexity Status Tags
High Easy TODO include-config, rspec-matcher
it { is_expected.to include_config(ConvenientService::Standard::Config) }

Notes:

  • This is a crucial task before the v1.0.0 release.

Introduce a middleware that cleans exception backtraces

Priority Complexity Status Tags
Medium Moderate TODO clean-backtrace

Introduce a respond_to-like way to process result statuses

Priority Complexity Status Tags
High Moderate TODO respond_to, pattern-matching

For example:

# before
result = Service.result(number: 4)

if result.success?
  # ...
elsif result.failure?
  if result.code.to_sym == :baz
    # ...
  elsif result.code.to_sym == :qux
    # ...
  end
else # result.error?
  if result.code.to_sym == :foo
    # ...
  elsif result.code.to_sym == :bar
    # ...
  end
end
# after
result = Service.result(number: 4)

result.respond_to do |status|
  status.success { }

  status.failure(code: :baz) { }
  status.failure(code: :qux) { }

  status.error(code: :foo) { }
  status.error(code: :bar) { }

  status.unexpected { }
end

Notes:

  • This is a crucial task before the v1.0.0 release.

Introduce per-request caching of steps using Rails Current Attributes

Priority Complexity Status Tags
Medium Moderate TODO per-request-cache, cached-steps, current-attributes

A killer feature.

Notes:


Introduce concurrent/parallel steps

Priority Complexity Status Tags
High Extreme TODO concurent-steps, parallel-steps

A killer feature.


Introduce recoverable services

Priority Complexity Status Tags
High Extreme TODO recoverable-services

A killer feature.


Introduce results enumerator

Priority Complexity Status Tags
Moderate Extreme TODO results-enumerator
enum = service.to_results_enum.lazy.select { ... }

result = enum.next

Introduce a DSL to add heredocs to failure and error messages

Priority Complexity Status Tags
Low Moderate TODO hereredoc, failures, errors

Track receive counts for delegate_to

Notes:


Consider to introduce DSL for high-order services

Priority Complexity Status Tags
Medium Hard TODO high-order-services

Consider to introduce delegate_to_service

Priority Complexity Status Tags
Low Moderate TODO delegate-to-service

Consider to introduce .and_return(instance_of(expected))

Priority Complexity Status Tags
Low Moderate TODO and_return, rspec-argument-matcher

Add a way to select diff algorithm

Priority Complexity Status Tags
Low Moderate TODO delegate_to, diff_algorithm, diffy

ConvenientService::Config.delegate_to_diff_algorithm = :diffy


Rubocop cop that complains when a service name does NOT start with a verb

Priority Complexity Status Tags
Low Hard TODO rubocop-cop, service-name, start-with-verb

Create a generator for service specs boilerplate

Priority Complexity Status Tags
High Hard TODO generator, specs-boilerplate

A killer feature.


Rubocop cop that complains when a service does NOT have its own suite of specs

Priority Complexity Status Tags
Medium Moderate TODO rubocop-cop, missing-direct-specs

Consider to introduce inline steps

Priority Complexity Status Tags
Medium Moderate TODO inline-steps

Allow to define method middleware caller with visibility

Priority Complexity Status Tags
Low Moderate TODO public, protected, private, method-middleware-caller

Introduce an ability to uninclude configs

Priority Complexity Status Tags
High High TODO config, uninclude

For example:

class Service
  include ConvenientService::Standard::Config

  include ConvenientService::FaultTolerance::Config

  uninclude ConvenientService::FaultTolerance::Config

  def result
    success
  end
end

Otherwise, the config inclusion API must be changed before v1.0.0.

Notes:


Consider to allow to pass positional arguments to steps

Priority Complexity Status Tags
Low Moderate TODO positional-arguments, steps

For example:

class Service
  include ConvenientService::Standard::Config

  step NestedService, in: [
    {0 => :foo},
    {1 => :bar}
  ]
end

Under the hood it is converted into:

def first_step
  @first_step ||= NestedService.result(foo, bar)
end

Minitest assertions

Priority Complexity Status Tags
Medium Moderate TODO minitest, assertions, matchers

Internals

Consider to replace CachesReturnValue

Priority Complexity Status Tags
Medium Moderate TODO performance-optimization, CachesReturnValue

Services and steps are caching their results utilizing the CachesReturnValue plugin.

Although it is very flexible and easy to reuse from a maintenance point of view, that is not the best option from a performance point of view.

If it starts to cause any visible performance penalty, it can be refactored using regular ||= or if defined?.


Consider creating parent results while copying results

Priority Complexity Status Tags
Medium Moderate TODO parent-result

Fallbacks have no access to their original results.

When a fallback result is used, the original result is NOT in the parent's chain.

Is it OK?


Consider making result codes Symbol descendants

Priority Complexity Status Tags
Medium Easy TODO result-code, case-when, symbol-descendant

This way the code below:

if result.not_success?
  case result.code.to_sym
  when :full_queue
    notify_devops
  when :duplicated_job
    notify_devs
  else
    # ...
  end
end

Can be rewritten as follows:

if result.not_success?
  case result.code
  when :full_queue
    notify_devops
  when :duplicated_job
    notify_devs
  else
    # ...
  end
end

That leads to more idiomatic and natural Ruby.


Pass method name to TooManyCommitsFromMethodMissing exception

Priority Complexity Status Tags
Medium Moderate TODO config, method-missing, auto-commit

The TooManyCommitsFromMethodMissing exception is already beneficial.

##
# `Service` config is committed too many times from `method_missing`.
# In order to resolve this issue try to commit it manually before usage of any config-dependent method.
#
# Example 1 (outside class):
#   # Commitment:
#   Service.commit_config!
#
#   # Few lines later - usage:
#   Service.result # or whatever method.
#
# Example 2 (inside class):
#
#   class Service
#     # ...
#     commit_config!
#
#     step :result # or any other method that becomes available after config commitment.
#   end

However, it does not give any information on which exact method causes too many method-missing invocations.


Move internals into Core

Priority Complexity Status Tags
Medium Moderate TODO internals, core

Notes:

  • Provide a simple way to add new instance/class methods to internals.

Extract auto commitment behavior from the Core into a separate concern

Priority Complexity Status Tags
Medium Hard TODO core, auto-commitment

Notes:

  • Ensure it can be easily integrated with other extractions, e,g: new middleware backend.

  • Probably inheritance is a compromise way to go for now.


Convert the Specification module into a singleton class

Priority Complexity Status Tags
Low Low TODO specification, gemspec, singleton
  • That is required to have a simple way to test the gemspec by RSpec.

    For example, the spec.files config is very error-prone, but it has no reliable specs for now.

    module ConvenientService
      class Specification
        include ::Singleton
    
        # ...
    
        def to_gemspec
          # ...
        end
      end
    end

Add Dockerfiles for TruffleRuby 23.0 and 24.0

Priority Complexity Status Tags
Low Moderate TODO truffle-ruby, dockerfile

Notes:


Provide a way to use trailing ENV variables in go-tasks

Priority Complexity Status Tags
Low Unknown TODO go-task, Taskfile, leading-env-variable, trailing-env-variable

The following command (task docker:build) works in both cases.

With leading ENV variables.

RUBY_ENGINE=ruby RUBY_VERSION=2.7 task docker:build

With trailing ENV variables.

task docker:build RUBY_ENGINE=ruby RUBY_VERSION=2.7

But at the same timetask rspec works only with leading ENV variables.

APPRAISAL=rails_7.0 task rspec

That is happening because task rspec accesses APPRAISAL using Dynamic Variables.

Notes:


Leverage RequestStore

Priority Complexity Status Tags
Medium Hard TODO request-store

Use RequestStore or RequestStore::Fibers when available? | Any additional changes for RequestStore::Sidekiq? Check RuboCop::ThreadSafety for details.


Do not use testing toolkit in the primitives layer

Priority Complexity Status Tags
Medium Moderate TODO layers

See Components Diagram + it should take the minimal amount of efforts to extract and reuse Utils, Suppport in the different projects.


Resolve warning during specs

Priority Complexity Status Tags
Medium Easy TODO warning, specs

Move callbacks and steps to internals

Priority Complexity Status Tags
Medium High TODO internals, callbacks, steps

In order to NOT pollute the public interface of users services.


Introduce custom RSpec matcher to track ConvenientService::Logger messages

Priority Complexity Status Tags
High Hard TODO logger, custom-matcher

Remove dependency containers

Priority Complexity Status Tags
Medium Easy TODO dependency-containers

Write custom middleware backend


Optimize stack.dup in MethodMiddlewares#call


Make a decision of what to do with printable_block in custom RSpec matchers


Consider to change/rewrite delegate backend to minify its interface


Ensure same order of attr macros, delegators, initialize, class methods, attr methods, queries, actions, to_*, comparison, inspect


Consider to create ComparableProc descendant from Proc

To abstract away block&.source_location != other.block&.source_location


Consider to use Struct as key in Support::Cache

To hide overriden eql?


Tests

Intentionally disable plugins to document dependencies


Mutant testing


Introduce thread-safety tests

Priority Complexity Status Tags
Medium Hard TODO thread-safety

Performance

Perfromance testing

rspec-benchmark, Testing object allocations, allocation_stats.


Measure performance of deeply nested steps

Priority Complexity Status Tags
Medium Moderate TODO performance, deeply-nested-steps

Measure performance of huge amount of included modules

Priority Complexity Status Tags
Medium Moderate TODO performance, included-modules

Loop middleware backends in performance benchmarks

Priority Complexity Status Tags
Medium Moderate TODO middleware-backend

Consider to extract common benchmark setup.


Memory

Consider to drop references to already calculated steps

Priority Complexity Status Tags
Low High TODO memory, drop-calculated-steps

Drawbacks:

  • Services that do NOT keep references to already calculated steps can NOT utilize CanHaveRollbacks plugin.

Compile middleware stacks.

Priority Complexity Status Tags
Medium High TODO compile, middleware-stack
module ConvenientService
  module Support
    module Middleware
      class StackBuilder
        module Constants
          module Backends
            ##
            # @return [Symbol]
            #
            COMPILED = :compiled
          end
        end
      end
    end
  end
end

Unify middleware backends interfaces

Priority Complexity Status Tags
Medium Moderate TODO middleware-backend, interface
def run(env, original)
  # ...
end

Cache unmodified configs.

Priority Complexity Status Tags
Medium High TODO cache, config

Licence

Complete licence files


Search for TODOs in the codebase or check discussions for more tasks.