Class: RSpecTracer::RemoteCache::UserTasks Private

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec_tracer/remote_cache/user_tasks.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.

Orchestrator for the user-facing ‘rspec_tracer:remote_cache:*` Rake tasks. Composes `GitAncestry` + a `Backend` implementation, drives the download (candidate-ref walk + first-valid wins) and upload (branch_ref + branch_refs update + retention prune) flows.

Called from ‘lib/rspec_tracer/remote_cache/Rakefile` which is loaded by the user’s own Rakefile per USER_FACING_SURFACE.md section 5. The user-facing task surface is preserved from 1.x bit-for-bit: same task names, same env vars, same exit behavior.

Graceful-degradation contract:

- `download!` catches every StandardError, logs, returns false.
  A failed download is cold run; tests still proceed.
- `upload!` catches every StandardError, logs, returns false.
  A failed upload is logged but doesn't propagate non-zero -
  the tests already passed; cache miss is recoverable next run.

Constant Summary collapse

BUILT_IN_BACKENDS =

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

Internal constant.

{
  s3: S3Backend,
  local_fs: LocalFsBackend,
  redis: RedisBackend
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration:, env:) ⇒ UserTasks

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.

Internal method on the tracer pipeline.



87
88
89
90
91
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 87

def initialize(configuration:, env:)
  @config = configuration
  @env = env
  @logger = configuration.logger
end

Class Method Details

.download!(configuration: RSpecTracer, env: ENV) ⇒ Boolean

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.

Module-level convenience for #download!. Equivalent to ‘UserTasks.new(configuration: …, env: …).download!`. Invoked by the bundled `rspec_tracer/remote_cache/Rakefile` shim that users `import` from their own `Rakefile`.

Parameters:

  • configuration (Object) (defaults to: RSpecTracer)

    anything responding to the ‘cache_path` / `logger` / `remote_cache_*` config surface (defaults to the RSpecTracer top-level module).

  • env (Hash) (defaults to: ENV)

    env hash to read ‘GIT_BRANCH` / `GIT_DEFAULT_BRANCH` from (defaults to `ENV`).

Returns:

  • (Boolean)

    true on a successful cache hit, false on cold run or graceful failure.



54
55
56
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 54

def self.download!(configuration: RSpecTracer, env: ENV)
  new(configuration: configuration, env: env).download!
end

.git_repo?Boolean

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.

Internal helper for the tracer pipeline.

Returns:

  • (Boolean)


81
82
83
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 81

def self.git_repo?
  system('git', 'rev-parse', 'HEAD', out: File::NULL, err: File::NULL)
end

.prune_all!(configuration: RSpecTracer, env: ENV) ⇒ Object

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.

Internal helper for the tracer pipeline.



75
76
77
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 75

def self.prune_all!(configuration: RSpecTracer, env: ENV)
  new(configuration: configuration, env: env).prune_all!
end

.upload!(configuration: RSpecTracer, env: ENV) ⇒ Boolean

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.

Module-level convenience for #upload!. Equivalent to ‘UserTasks.new(configuration: …, env: …).upload!`. Invoked by the bundled `rspec_tracer/remote_cache/Rakefile` shim.

Parameters:

  • configuration (Object) (defaults to: RSpecTracer)

    anything responding to the ‘cache_path` / `logger` / `remote_cache_*` config surface (defaults to the RSpecTracer top-level module).

  • env (Hash) (defaults to: ENV)

    env hash to read ‘GIT_BRANCH` / `GIT_DEFAULT_BRANCH` from (defaults to `ENV`).

Returns:

  • (Boolean)

    true on a successful upload, false on graceful failure (logged but not raised).



69
70
71
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 69

def self.upload!(configuration: RSpecTracer, env: ENV)
  new(configuration: configuration, env: env).upload!
end

Instance Method Details

#download!Boolean

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.

Pull the closest matching cache for the current branch + commit ancestry from the configured backend. Walks the candidate refs produced by GitAncestry, downloads + extracts the first ref whose archive validates, and returns true. Cold-run on miss.

Errors are caught and logged; a failed download never propagates a non-zero exit into the test suite (graceful degradation).

Examples:

In a Rakefile

require 'rspec_tracer/remote_cache/Rakefile'
# provides `rake rspec_tracer:remote_cache:download` which
# invokes RSpecTracer::RemoteCache::UserTasks.download!

Returns:

  • (Boolean)

    true on a successful download, false on cold run / graceful failure.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 108

def download!
  ancestry = build_ancestry
  ancestry.merge_base_branch!
  backend = build_backend(ancestry)

  refs = candidate_refs(ancestry, backend)
  if refs.empty?
    @logger.warn 'rspec-tracer remote_cache: no cache candidates found; cold run'
    return false
  end

  tree_sha = head_tree_sha
  refs.each do |ref|
    @logger.debug "rspec-tracer remote_cache: trying ref #{ref}"
    return true if backend.download(ref, tree_sha: tree_sha)
  end

  @logger.warn 'rspec-tracer remote_cache: no suitable cache found; cold run'
  false
rescue StandardError => e
  @logger.warn "rspec-tracer remote_cache: download failed (#{e.class}: #{e.message}); cold run"
  false
end

#prune_all!Object

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.

Cross-tier PR-branch prune. Walks every branch under the configured prefix and deletes whole branches idle longer than ‘cache_retention_pr_branch_ttl_seconds`. Designed as a periodic maintenance task (nightly cron) - dead PR branches whose tip is never re-uploaded otherwise accumulate forever because `maybe_prune` only scopes to the current upload’s tier. Returns the total refs removed across all branches, or 0 on graceful failure.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 168

def prune_all!
  ttl = safe_config(:cache_retention_pr_branch_ttl_seconds)
  if ttl.nil?
    @logger.warn 'rspec-tracer remote_cache: prune_all requires cache_retention_pr_branch_ttl; skipping'
    return 0
  end

  backend = build_backend(build_admin_ancestry)
  removed = backend.prune_all!(pr_branch_ttl_seconds: ttl)
  @logger.debug "rspec-tracer remote_cache: prune_all removed #{removed} refs"
  removed
rescue StandardError => e
  @logger.warn "rspec-tracer remote_cache: prune_all failed (#{e.class}: #{e.message})"
  0
end

#upload!Boolean

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.

Push the local cache directory for the current branch + commit to the configured backend, refresh the per-branch ref index, and apply retention pruning.

Errors are caught and logged; a failed upload never propagates non-zero into the test suite (the tests already passed).

Examples:

In a Rakefile

require 'rspec_tracer/remote_cache/Rakefile'
# provides `rake rspec_tracer:remote_cache:upload` which
# invokes RSpecTracer::RemoteCache::UserTasks.upload!

Returns:

  • (Boolean)

    true on success, false on graceful failure.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/rspec_tracer/remote_cache/user_tasks.rb', line 145

def upload!
  ancestry = build_ancestry
  ancestry.merge_base_branch!
  backend = build_backend(ancestry)

  backend.upload(ancestry.branch_ref, tree_sha: head_tree_sha)
  maybe_update_branch_refs(backend, ancestry)
  maybe_prune(backend, ancestry)
  maybe_warn_unbounded(backend)
  true
rescue StandardError => e
  @logger.warn "rspec-tracer remote_cache: upload failed (#{e.class}: #{e.message})"
  false
end