Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
ef30b5d
Basic CCC store and message
ismasan Feb 20, 2026
6758e11
Read and append with consistency guard
ismasan Feb 20, 2026
8737661
Add consumer group support with partition-based offset tracking
ismasan Feb 20, 2026
8772eb6
Return ConsistencyGuard from claim_next for optimistic concurrency
ismasan Feb 20, 2026
ac0b674
Use Message.to_conditions for type-aware guard conditions
ismasan Feb 20, 2026
a77102b
Cache payload_attribute_names at define time
ismasan Feb 20, 2026
6581cbc
Update partition plan with implemented semantics
ismasan Feb 21, 2026
0342f2c
Add YARD comments to CCC::Store methods
ismasan Feb 21, 2026
bd3be9f
Add YARD comments to CCC::Message, QueryCondition, ConsistencyGuard
ismasan Feb 21, 2026
0444e2a
Add causation_id, correlation_id, and #correlate to CCC::Message
ismasan Feb 21, 2026
ff63b2a
Add replaying flag to claim_next based on highest acked position
ismasan Feb 21, 2026
732fd2c
Return ClaimResult Data struct from Store#claim_next
ismasan Feb 21, 2026
8c17f0f
Add CCC reactor abstraction layer (Decider, Projector, Router)
ismasan Feb 21, 2026
50ac8c9
Fix causation chain: reactions correlate with event, not command
ismasan Feb 21, 2026
9ddceba
Support simple Consumer-only reactors without Decider/Projector
ismasan Feb 21, 2026
58a3b80
Add CCC.load for synchronous reactor state loading with AND-filtered …
ismasan Feb 21, 2026
11d0614
Add CCC background dispatch infrastructure (Worker, Dispatcher, notif…
ismasan Feb 21, 2026
28c63b7
Add CCC stale claim reaper with worker heartbeats
ismasan Feb 21, 2026
0cce1b5
Add CCC::Supervisor as top-level process entry point
ismasan Feb 21, 2026
0f5e311
Add CCC::Configuration and module-level API (config, configure, regis…
ismasan Feb 21, 2026
2fbf355
Add StoreInterface to guard CCC::Configuration#store= assignment
ismasan Feb 21, 2026
ee383e3
StateStored and EventSourced projectors for CCC
ismasan Feb 22, 2026
d48dc4e
Add CCC error handling parity with SequelBackend
ismasan Feb 22, 2026
9b9bc46
Error logging
ismasan Feb 22, 2026
381cbf7
CCC::Command and CCC::Event subclasses with their own registries
ismasan Feb 22, 2026
9253938
Add CCC.handle! for synchronous command handling in web controllers
ismasan Feb 22, 2026
432caeb
Add CCC module README with API docs and usage examples
ismasan Feb 28, 2026
926fd12
Accept #group_id objects in CCC Store consumer group methods
ismasan Feb 28, 2026
ce82396
Syntax
ismasan Mar 11, 2026
0e1901c
Design refs not in repo
ismasan Mar 11, 2026
7e579ae
Fix missing vars
ismasan Mar 11, 2026
84ea18f
Add #dispatch helper to CCC::Decider, allow resolving message classes…
ismasan Mar 11, 2026
68df28d
Add CCC scheduled message support
ismasan Mar 11, 2026
7251e03
Document CCC retries and backoff
ismasan Mar 11, 2026
dc5058c
New 'failed' consumer group status, and ErrorStrategy#on_fail
ismasan Mar 12, 2026
189b81a
fail status for CCC consumer groups
ismasan Mar 12, 2026
c6c5be2
Add CCC::Store#stats for monitoring and debugging
ismasan Mar 12, 2026
d523210
Include error_context in CCC::Store#stats and document stats API
ismasan Mar 12, 2026
949bb51
Add CCC::Store#read_correlation_batch for tracing causal chains
ismasan Mar 12, 2026
5c21da5
Add YARD examples to CCC::Store#read_partition
ismasan Mar 12, 2026
d6dc34e
Add CCC::Store#read_all for paginating the global event log
ismasan Mar 12, 2026
52450ef
CCC::Topology
ismasan Mar 12, 2026
039db1f
Falcon integration for Sourced::CCC with deferred configuration (to r…
ismasan Mar 12, 2026
59c3ceb
Add CCC::Falcon::Environment and Service with post-fork setup, update…
ismasan Mar 12, 2026
822d932
Revert "Add CCC::Falcon::Environment and Service with post-fork setup…
ismasan Mar 12, 2026
55be5e0
Falcon support
ismasan Mar 12, 2026
0f499d1
Remove CCC::Configuration#register
ismasan Mar 12, 2026
b0fd092
Support Sequel migrations, install store tables from migration
ismasan Mar 12, 2026
8daadae
Document CCC Sequel migration support
ismasan Mar 12, 2026
3938e9f
handle_batch -> handle_claim
ismasan Mar 12, 2026
fad69ed
Make reactors support .handle_batch
ismasan Mar 12, 2026
6d0c253
no need for argument
ismasan Mar 12, 2026
b6f034e
Replicate with_reactor RSpec helper for CCC
ismasan Mar 12, 2026
f92f298
Lazy-load CCC::Store
ismasan Mar 12, 2026
e20bc1c
Update offsets in a transaction to avoid locking on SQLite's single w…
ismasan Mar 12, 2026
3076cef
Add CCC::CommandContext for building commands from raw attributes
ismasan Mar 13, 2026
95a3314
Add order: :desc option to Store#read_all for reverse-chronological b…
ismasan Mar 13, 2026
cd92ea1
Return ReadAllResult from Store#read_all with Enumerable, to_enum, an…
ismasan Mar 13, 2026
67c3d9d
Change QueryCondition to support compound attrs with AND semantics
ismasan Mar 13, 2026
7bb9685
Extract condition_position_subqueries to deduplicate query_messages a…
ismasan Mar 13, 2026
bb0c9de
Change partition_values from Array to Hash for self-documenting key a…
ismasan Mar 13, 2026
064f01e
Fix composite partition false positives in find_and_claim_partition
ismasan Mar 13, 2026
19fb368
Add index on offsets(consumer_group_id, claimed) for faster partition…
ismasan Mar 13, 2026
78d5ad7
Logline
ismasan Mar 13, 2026
b03b4d4
CCC::Sync.after_sync actions run after the DB transaction
ismasan Mar 14, 2026
68f55ce
Document
ismasan Mar 14, 2026
c4137bb
Add missing specs for CCC::Message
ismasan Mar 14, 2026
c3a7825
Add specs for CCC::Message#with_payload
ismasan Mar 14, 2026
e911969
Add per-message and `any` callback hooks to CCC::CommandContext
ismasan Mar 14, 2026
5fdcf72
Support multiple message types in CommandContext.on
ismasan Mar 14, 2026
2c06711
Allow multiple `on` blocks per command type in CommandContext
ismasan Mar 14, 2026
36db6d1
Run CCC::CommandContext hooks in context of instance
ismasan Mar 14, 2026
fa9a31d
Lazy offset discovery in CCC::Store#claim_next
ismasan Mar 15, 2026
8c31b49
Replace CROSS JOIN with streaming iteration in find_and_claim_partition
ismasan Mar 15, 2026
e16b897
Order discovery results by min_pos to prevent skipping partitions
ismasan Mar 15, 2026
b8afa24
Use CTEs in discovery and fetch queries to halve key_pairs JOINs
ismasan Mar 15, 2026
c1831be
Skip caught-up offsets in find_and_claim_partition
ismasan Mar 15, 2026
dd4d40f
Add timing logs to CCC::Router for profiling
ismasan Mar 15, 2026
bc8f029
Short-circuit idle polls in claim_next via types_max_pos check
ismasan Mar 15, 2026
6fc497e
Add scaling benchmark with HTML charts
ismasan Mar 15, 2026
999f77b
Add scenario descriptions to scaling benchmark charts
ismasan Mar 15, 2026
1b3659f
Skip offset scan when undiscovered messages exist
ismasan Mar 15, 2026
bd5af3d
Remove known_keys Set from discovery — rely on INSERT OR IGNORE
ismasan Mar 15, 2026
85c2e9b
Add Store#append benchmark as baseline for eager offset creation
ismasan Mar 16, 2026
c556cad
Optimise append: eliminate redundant SELECT queries
ismasan Mar 16, 2026
0153cfa
Fix claim_next short-circuit and add eager offset creation
ismasan Mar 16, 2026
6afd4a8
Scaling bench
ismasan Mar 16, 2026
7b6303f
Bench results
ismasan Mar 16, 2026
4af46ab
Fix idle poll regression: replace broken min/max short-circuit with c…
ismasan Mar 16, 2026
935c0a5
Add consumer group lifecycle hooks via Router
ismasan Mar 16, 2026
939910a
Make CCC::Store#read_all from_position inclusive
ismasan Mar 17, 2026
985568a
Add CCC::Store#read_offsets for paginated offset inspection
ismasan Mar 17, 2026
d568007
Remove logging
ismasan Mar 18, 2026
f3af89a
Rename from_position: to after_position: in CCC::Store#read call stack
ismasan Mar 18, 2026
af56568
Add CCC::Message::Registry#all for recursive enumeration
ismasan Mar 18, 2026
c184ac5
Add conditions filter to CCC::Store#read_all
ismasan Apr 14, 2026
c2a54a4
Encapsulate Dispatcher setup and spawning into class level CCC::Dispa…
ismasan Apr 14, 2026
003548d
Remove redundant names
ismasan Apr 14, 2026
23a3433
PositionedMessage#to_message and Message.===
ismasan Apr 15, 2026
109ee36
Make all #handle_batch signatures the same so that GWT helpers work f…
ismasan Apr 15, 2026
9985ffa
Re-implement DurableWorkflow for CCC
ismasan Apr 15, 2026
235b365
Implement CCC::DurableWorkflow#handle_batch and rewrite tests to use …
ismasan Apr 15, 2026
d0e0540
Promote CCC to top-level Sourced namespace
ismasan Apr 15, 2026
05bf988
Simplify
ismasan Apr 15, 2026
582e163
Improve README
ismasan Apr 15, 2026
053a75c
Untrack examples/app
ismasan Apr 15, 2026
931d53a
Untrack bench files
ismasan Apr 15, 2026
e1a6a78
Ignore bench/ for now
ismasan Apr 15, 2026
d95dd57
Update CLAUDE.md to reflect CCC APIs
ismasan Apr 15, 2026
42135c3
Update README
ismasan Apr 15, 2026
e76d3b1
Style tweaks
ismasan Apr 16, 2026
f621f7b
Defer reactions in Decider.handle_batch
ismasan Apr 16, 2026
03fd28f
Move correlation into Actions::Append/Schedule
ismasan Apr 16, 2026
1ae600e
Sourced.load(upto:) loads history up to specific position number
ismasan Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ logs/
pkg
.DS_Store
.claude
bench/

211 changes: 126 additions & 85 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,135 +4,176 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

Sourced is an Event Sourcing / CQRS library for Ruby built around the "Decide, Evolve, React" pattern. It provides eventual consistency by default with an actor-like execution model for building event-sourced applications.
Sourced is a Ruby library for **aggregateless, stream-less event sourcing**. Messages go into a flat, globally-ordered log (SQLite via Sequel). Consistency context is assembled dynamically by querying relevant facts via key-value pairs extracted from event payloads, rather than being pre-assigned to fixed streams. Reactors declare partition keys which the store uses to build query conditions and claim work.

## Core Architecture

### Key Components
- **Actors**: Classes that hold state, handle commands, produce events, and react to events (lib/sourced/actor.rb)
- **Commands**: Intents to effect change in the system
- **Events**: Facts describing state changes that have occurred
- **Projectors**: React to events to build views, caches, or other representations (lib/sourced/projector.rb)
- **Backends**: Storage adapters (ActiveRecord, Sequel, test backend) in lib/sourced/backends/
- **Router**: Routes commands and events to appropriate handlers (lib/sourced/router.rb)
- **Supervisor**: Manages background worker processes (lib/sourced/supervisor.rb)
### Key abstractions

### Message Flow
Commands → Actors (Decide) → Events → Storage → Reactors (React) → New Commands
- **Message** (`lib/sourced/message.rb`) — base class for all commands/events. No `stream_id` or `seq`; gets a global `position` when stored. Provides `causation_id` / `correlation_id`, `#correlate`, `#extracted_keys`, and a `Registry`. Subclasses: `Sourced::Command`, `Sourced::Event`.
- **Store** (`lib/sourced/store.rb`) — SQLite-backed append-only log with key-pair indexing, consumer groups, scheduled messages, and stale-claim reaping. Returns `ReadResult`, `ClaimResult`, `ConsistencyGuard`, `PositionedMessage`, `Stats`, `OffsetsResult`, `ReadAllResult`.
- **Reactor base classes** — all `extend Sourced::Consumer` and declare `partition_by :key` (+ other keys) to define their consistency boundary:
- `Decider` (`lib/sourced/decider.rb`) — handles commands, produces events via `event` helper.
- `Projector` (`lib/sourced/projector.rb`) — builds read models. Two flavors: `Projector::StateStored` and `Projector::EventSourced`.
- `DurableWorkflow` (`lib/sourced/durable_workflow.rb`) — long-running workflows with step memoisation via `durable`/`wait`/`context`/`execute` and `catch(:halt)`.
- Plain `Consumer` reactors (extend `Sourced::Consumer` directly) for side-effect-only handlers.
- **Mixins**: `Sourced::Evolve` (state evolution from history), `Sourced::React` (event → command/event reactions), `Sourced::Sync` (post-append side effects).
- **Router** (`lib/sourced/router.rb`) — registers reactors, dispatches claimed batches, manages consumer-group lifecycle hooks.
- **Dispatcher / Worker / WorkQueue** (`lib/sourced/{dispatcher,worker,work_queue}.rb`) — claim-and-drain processing; signal-driven via `InlineNotifier` + `CatchUpPoller`.
- **StaleClaimReaper** (`lib/sourced/stale_claim_reaper.rb`) — releases abandoned partition claims from dead workers via heartbeats.
- **ScheduledMessagePoller** (`lib/sourced/scheduled_message_poller.rb`) — promotes due scheduled messages into the main log.
- **Supervisor** (`lib/sourced/supervisor.rb`) — top-level process entry point wiring Dispatcher, executor, and reactors.
- **CommandContext** (`lib/sourced/command_context.rb`) — builds commands from raw attributes; supports per-message and `any` hooks.
- **Topology** (`lib/sourced/topology.rb`) — graph of reactors / message flows.
- **Installer + migrations** (`lib/sourced/installer.rb`, `lib/sourced/migrations/`) — Sequel migration template for installing store tables.
- **Falcon integration** (`lib/sourced/falcon/`) — `Environment` + `Service` for deferred post-fork setup.

### Concurrency Model
Sourced processes events by acquiring locks on `[reactor_group_id][stream_id]` combinations, ensuring sequential processing within streams while allowing concurrent processing across different streams.
### Message flow

`Command → Decider.decide → Events → Store.append → Router claims → Reactor.handle_claim → (Projections / Sync actions)`

Reactions are **deferred**: a Decider's `react` blocks don't run inline with the command that produced the triggering event. When the Decider appends events, its own subscription (`handled_messages_for_react`) picks them up on the next claim cycle and runs the reaction in a separate `handle_batch`. Consequence: the originating command's `after_sync` commits as soon as its events commit, not after reactions finish. Trade-off: command and reactions are no longer in the same transaction — a failing reaction does not roll back the command.

All reactors implement `.handle_claim(claim, history:)` and/or `.handle_batch(partition_values, new_messages, history:, replaying:)` with a uniform signature so GWT helpers and partial-ack logic work across types.

### Partition-based consistency

Reactors declare `partition_by :key1, :key2`. The store indexes every payload attribute into `sourced_key_pairs` at append time, and reads use AND-filtered conditions over these keys. `ConsistencyGuard` (returned by `read` / `claim_next`) detects conflicting appends via `messages_since(conditions, position)`.

## Development Commands

### Testing
```bash
# Run all tests (default rake task)
rake

# Run specific test file
bundle exec rspec spec/actor_spec.rb

# Run backend tests
bundle exec rspec spec/backends/
```bash
# Full suite
bundle exec rake

# Run with specific database (PostgreSQL required for some tests)
DATABASE_URL=postgres://localhost/sourced_test bundle exec rspec
# Specific file
bundle exec rspec spec/store_spec.rb
bundle exec rspec spec/decider_spec.rb
```

### Database Setup for Tests
The gem supports multiple backends:
- PostgreSQL (via Sequel or ActiveRecord)
- SQLite (via Sequel or ActiveRecord)
- In-memory test backend
Tests use in-memory SQLite by default. `spec/store_spec.rb` is the central integration suite; `spec/testing/rspec_spec.rb` covers the GWT helpers in `lib/sourced/testing/rspec.rb`.

Test databases are automatically created/cleared by the test suite.
### Console

### Console/IRB
```bash
# Interactive console for experimentation
bin/console
```

## Configuration Patterns
## Configuration

### Backend Configuration
```ruby
# PostgreSQL via Sequel (default production setup)
Sourced.configure do |config|
config.backend = Sequel.connect(ENV.fetch('DATABASE_URL'))
config.store = Sequel.sqlite('my_app.db') # auto-wraps in Sourced::Store
# or: config.store = Sourced::Store.new(db)
# or: any object matching Configuration::StoreInterface
config.worker_count = 2
config.batch_size = 50
config.catchup_interval = 5
config.claim_ttl_seconds = 120
end

# Test backend (default, in-memory)
Sourced.configure do |config|
config.backend = Sourced::Backends::TestBackend.new
end
```

### Registering Components
```ruby
# Register actors and projectors for background processing
Sourced.register(SomeActor)
Sourced.register(SomeDecider)
Sourced.register(SomeProjector)
```

## Key DSL Patterns
- `Sourced.configure` stores the block and calls `setup!`; re-runnable post-fork to re-establish DB connections (used by Falcon integration).
- `Sourced.store`, `Sourced.router`, `Sourced.topology`, `Sourced.reset!` — module-level accessors.
- `Sourced.handle!(ReactorClass, command)` — synchronous command dispatch (for web controllers): validates, loads history via partition read, decides, appends with guard, advances registered offsets. Returns `HandleResult(command, reactor, events)`.
- `Sourced.load(ReactorClass, **partition_values)` — loads a reactor instance by evolving over AND-filtered partition history. Returns `[instance, read_result]`.

## DSL Patterns

### Decider

### Actor Definition
```ruby
class SomeActor < Sourced::Actor
# Initial state factory
state do |id|
{ id: id, status: 'new' }
end

# Command handler
command :create_something, name: String do |state, cmd|
event :something_created, cmd.payload
class Courses < Sourced::Decider
partition_by :course_id

command CreateCourse do |_state, cmd|
event CourseCreated, course_id: cmd.payload.course_id, course_name: cmd.payload.course_name
end
# Event handler (state evolution)
event :something_created, name: String do |state, event|
state[:name] = event.payload.name

event CourseCreated do |state, evt|
state[:course_id] = evt.payload.course_id
state[:name] = evt.payload.course_name
end

# Reaction (workflow orchestration)
reaction :something_created do |event|
stream_for(event).command :next_step

reaction CourseCreated do |evt|
dispatch SendWelcomeEmail, course_id: evt.payload.course_id
end
end
```

### Message Definitions
### Message definition

```ruby
# Expanded syntax for complex validation/coercion
CreateLead = Sourced::Command.define('leads.create') do
attribute :name, Types::String.present
attribute :email, Types::Email.present
CreateCourse = Sourced::Command.define('courses.create') do
attribute :course_id, Types::String.present
attribute :course_name, Types::String.present
end

LeadCreated = Sourced::Event.define('leads.created') do
attribute :name, String
attribute :email, String
CourseCreated = Sourced::Event.define('courses.created') do
attribute :course_id, String
attribute :course_name, String
end
```

## Backend Implementation Notes
`Sourced::Command` and `Sourced::Event` each have their own `Registry` (both reachable from `Sourced::Message.registry` via recursive lookup).

### Projector flavors

- `Projector::StateStored` — evolves only the claimed batch on top of the stored state snapshot.
- `Projector::EventSourced` — evolves from full history every claim (via `context_for`).

### Scheduled / delayed messages

```ruby
cmd = SendReminder.new(payload: { course_id: 'c1' }).at(Time.now + 3600)
store.schedule_messages([cmd])
store.update_schedule! # manual promotion (normally done by ScheduledMessagePoller)
```

In reactions: `dispatch(Cmd, ...).at(time)`.

## Store API highlights

- All backends must implement the BackendInterface defined in lib/sourced/configuration.rb
- SequelBackend is the main production backend (lib/sourced/backends/sequel_backend.rb)
- ActiveRecordBackend provides Rails integration (lib/sourced/backends/active_record_backend.rb)
- TestBackend provides in-memory storage for testing (lib/sourced/backends/test_backend.rb)
- `append(messages, guard: nil)` — writes + auto-indexes payload keys; raises `ConcurrentAppendError` if guard is violated.
- `read(conditions, after_position:, limit:)` → `ReadResult(messages, guard)`.
- `read_partition(partition_attrs, handled_types:)` — AND-filtered read for loading reactor state.
- `read_all(after_position:, limit:, order: :asc, conditions: nil)` → `ReadAllResult` (lazy pagination via `to_enum`).
- `claim_next(reactor, worker_id:)` → `ClaimResult` with partition batch + guard. Supports compound partitions and replaying flag.
- `ack(claim, last_position:)` / `release(claim)` / `advance_offset(group_id, partition:, position:)`.
- `register_consumer_group`, `start_consumer_group`, `stop_consumer_group`, `reset_consumer_group`.
- `read_offsets(group_id:, limit:, from_id:)` → `OffsetsResult` (cursor-paginated, `to_enum`).
- `stats` → `Stats(max_position, groups)` including `error_context`.
- `worker_heartbeat` / `release_stale_claims` — claim liveness.

## Testing Considerations
## Testing

- Use shared examples from spec/shared_examples/backend_examples.rb when testing backends
- Time manipulation available via Timecop gem
- Database isolation handled automatically per test
- Concurrent testing patterns available for testing race conditions
- `lib/sourced/testing/rspec.rb` provides GWT helpers (`given`/`when_`/`then_`) usable across all reactor types since `#handle_batch` has a uniform signature.
- Shared store behaviour concentrated in `spec/store_spec.rb` (2400+ lines).
- Durable workflow specs demonstrate the step-memoisation pattern.

## Error Handling

- Default error strategy logs exceptions and stops consumer groups
- Configurable retry/backoff strategies available
- Consumer groups can be stopped/started programmatically via backend API
- `error_strategy` on `Configuration` — configurable retry / backoff / fail. See `lib/sourced/error_strategy.rb`.
- Consumer groups have `running` / `stopped` / `failed` states. `on_fail` fires on terminal failures.
- `PartialBatchError` carries successfully-processed `action_pairs` plus the failing message so batches can be partially acked.

## Key Files

- Entrypoint: `lib/sourced.rb` (top-level API, `handle!`, `load`)
- Store: `lib/sourced/store.rb` + `lib/sourced/installer.rb` + `lib/sourced/migrations/`
- Reactors: `lib/sourced/{decider,projector,durable_workflow,consumer}.rb`
- Mixins: `lib/sourced/{evolve,react,sync}.rb`
- Dispatch: `lib/sourced/{dispatcher,worker,work_queue,stale_claim_reaper,scheduled_message_poller,inline_notifier}.rb`
- Router/topology: `lib/sourced/{router,topology}.rb`
- Messages: `lib/sourced/message.rb` (includes `QueryCondition`, `ConsistencyGuard`)
- Falcon: `lib/sourced/falcon/{environment,service}.rb`
- Testing: `lib/sourced/testing/rspec.rb`

## Local scratch (untracked)

`examples/app/` and `bench/*` are intentionally untracked (see commits `Untrack examples/app` / `Untrack bench files`). Files may exist locally for experimentation but must not be re-added to the repo without explicit approval.
2 changes: 0 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ group :development do
end

group :test do
gem 'dotenv'
gem 'pg'
gem 'rspec', '~> 3.0'
gem 'sequel'
gem 'sqlite3'
Expand Down
4 changes: 0 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ GEM
irb (~> 1.10)
reline (>= 0.3.8)
diff-lcs (1.5.1)
dotenv (3.1.4)
fiber-annotation (0.2.0)
fiber-local (1.1.0)
fiber-storage
Expand All @@ -57,7 +56,6 @@ GEM
parser (3.3.7.1)
ast (~> 2.4.1)
racc
pg (1.5.8)
plumb (0.0.17)
bigdecimal
concurrent-ruby
Expand Down Expand Up @@ -119,9 +117,7 @@ PLATFORMS
DEPENDENCIES
debug
docco!
dotenv
logger
pg
rake (~> 13.0)
rspec (~> 3.0)
rubocop
Expand Down
Loading