Class: Mongoid::Contextual::Mongo::DocumentsLoader Private

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Association::EagerLoadable
Defined in:
lib/mongoid/contextual/mongo/documents_loader.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Loads documents for the provided criteria.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Association::EagerLoadable

#eager_load, #eager_loadable?, #preload

Constructor Details

#initialize(view, klass, criteria, executor: self.class.executor) ⇒ DocumentsLoader

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instantiates the document loader instance and immediately schedules its execution using the provided executor.

Parameters:

  • view (Mongo::Collection::View)

    The collection view to get records from the database.

  • klass (Class)

    Mongoid model class to instantiate documents. All records obtained from the database will be converted to an instance of this class, if possible.

  • criteria (Mongoid::Criteria)

    Criteria that specifies which documents should be loaded.

  • executor (Concurrent::AbstractExecutorService) (defaults to: self.class.executor)

    Executor that is capable of running ‘Concurrent::Promises::Future` instances.



89
90
91
92
93
94
95
96
97
98
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 89

def initialize(view, klass, criteria, executor: self.class.executor)
  @view = view
  @klass = klass
  @criteria = criteria
  @mutex = Mutex.new
  @state = :pending
  @future = Concurrent::Promises.future_on(executor) do
    start && execute
  end
end

Instance Attribute Details

#criteriaMongoid::Criteria

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Criteria that specifies which documents should be loaded. Exposed here because ‘eager_loadable?` method from `Association::EagerLoadable` expects this to be available.

Returns:

  • (Mongoid::Criteria)

    Criteria that specifies which documents should be loaded. Exposed here because ‘eager_loadable?` method from `Association::EagerLoadable` expects this to be available.



75
76
77
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 75

def criteria
  @criteria
end

Class Method Details

.executor(name = Mongoid.async_query_executor) ⇒ Concurrent::ImmediateExecutor | Concurrent::ThreadPoolExecutor

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns suitable executor according to Mongoid config options.

Parameters:

  • name (String | Symbol) (defaults to: Mongoid.async_query_executor)

    The query executor name, can be either :immediate or :global_thread_pool. Defaulted to ‘async_query_executor` config option.

Returns:

  • (Concurrent::ImmediateExecutor | Concurrent::ThreadPoolExecutor)

    The executor to be used to execute document loading tasks.

Raises:



61
62
63
64
65
66
67
68
69
70
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 61

def self.executor(name = Mongoid.async_query_executor)
  case name.to_sym
  when :immediate
    immediate_executor
  when :global_thread_pool
    global_thread_pool_async_query_executor
  else
    raise Errors::InvalidQueryExecutor.new(name)
  end
end

.global_thread_pool_async_query_executorConcurrent::ThreadPoolExecutor

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns asynchronous executor to be used when async_query_executor config option is set to :global_thread_pool. This executor runs operations on background threads using a thread pool.

Returns:

  • (Concurrent::ThreadPoolExecutor)

    The executor to be used to execute document loading tasks.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 32

def self.global_thread_pool_async_query_executor
  create_pool = Proc.new do |concurrency|
    Concurrent::ThreadPoolExecutor.new(
      min_threads: 0,
      max_threads: concurrency,
      max_queue: concurrency * 4,
      fallback_policy: :caller_runs
    )
  end
  concurrency = Mongoid.global_executor_concurrency || 4
  @@global_thread_pool_async_query_executor ||= create_pool.call(concurrency)
  if @@global_thread_pool_async_query_executor.max_length != concurrency
    old_pool = @@global_thread_pool_async_query_executor
    @@global_thread_pool_async_query_executor = create_pool.call(concurrency)
    old_pool.shutdown
  end
  @@global_thread_pool_async_query_executor
end

.immediate_executorConcurrent::ImmediateExecutor

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns synchronous executor to be used when async_query_executor config option is set to :immediate. This executor runs all operations on the current thread, blocking as necessary.

Returns:

  • (Concurrent::ImmediateExecutor)

    The executor to be used to execute document loading tasks.



22
23
24
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 22

def self.immediate_executor
  @@immediate_executor ||= Concurrent::ImmediateExecutor.new
end

Instance Method Details

#executeArray<Mongoid::Document>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Loads records specified by ‘@criteria` from the database, and convert them to Mongoid documents of `@klass` type.

This method is called by the task (possibly asynchronous) scheduled when creating an instance of the loader. However, this method can be called directly, if it is desired to execute loading on the caller thread immediately.

Calling this method does not change the state of the loader.

Returns:



152
153
154
155
156
157
158
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 152

def execute
  documents = @view.map do |doc|
    Factory.from_db(@klass, doc, @criteria)
  end
  eager_load(documents) if eager_loadable?
  documents
end

#pending?true | false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns false or true whether the loader is in pending state.

Pending state means that the loader execution has been scheduled, but has not been started yet.

Returns:

  • (true | false)

    true if the loader is in pending state, otherwise false.



107
108
109
110
111
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 107

def pending?
  @mutex.synchronize do
    @state == :pending
  end
end

#started?true | false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns false or true whether the loader is in started state.

Started state means that the loader execution has been started. Note that the loader stays in this state even after the execution completed (successfully or failed).

Returns:

  • (true | false)

    true if the loader is in started state, otherwise false.



121
122
123
124
125
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 121

def started?
  @mutex.synchronize do
    @state == :started
  end
end

#unscheduleObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Mark the loader as unscheduled.

If the loader is marked unscheduled, it will not be executed. The only option to load the documents is to call ‘execute` method directly.

Please note that if execution of a task has been already started, unscheduling does not have any effect.



134
135
136
137
138
# File 'lib/mongoid/contextual/mongo/documents_loader.rb', line 134

def unschedule
  @mutex.synchronize do
    @state = :cancelled unless @state == :started
  end
end