-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This service will retreive the associated urn for an application that exists in the database. When the availabe urn set is exhausted it will increase its size automatically.
- Loading branch information
1 parent
6e9281d
commit 1d06010
Showing
2 changed files
with
116 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# | ||
# build a pseudo random urns list with the existing urns removed from that list | ||
# and we calculate the global index of the current application based on list sorted by created_at | ||
# then we get the urn located at the determined application index | ||
# | ||
|
||
class Application::Urn | ||
class << self | ||
def reset_urns | ||
const_set(:URNS, build_urns) | ||
nil | ||
end | ||
|
||
def build_urns | ||
{ | ||
"teacher" => build_list("TE"), | ||
"salaried_trainee" => build_list("ST"), | ||
}.freeze | ||
end | ||
|
||
def build_list(code) | ||
su_size = LENGTH.to_s.size | ||
Array | ||
.new(LENGTH) { [PREFIX, code, sprintf("%0##{su_size}d", _1)].join } | ||
.drop(1) | ||
.shuffle! | ||
end | ||
end | ||
|
||
LENGTH = 99_999 | ||
PREFIX = "IRP".freeze | ||
URNS = build_urns | ||
|
||
def initialize(application) | ||
@application = application | ||
end | ||
|
||
def urn | ||
MUTEX.synchronize do | ||
increase_suffix if urns_exhausted? | ||
available_urns[application_index] | ||
end | ||
end | ||
|
||
private | ||
|
||
def increase_suffix | ||
self.class.const_set(:LENGTH, "#{self.class::LENGTH}9".to_i) | ||
self.class.reset_urns | ||
end | ||
|
||
def urns_exhausted? | ||
application_index > available_urns.size | ||
end | ||
|
||
def application_index | ||
return @application_index if @application_index | ||
|
||
@application_index = FindApplicationIndexQuery | ||
.new(application_id: @application.id) | ||
.execute | ||
.to_a | ||
.dig(0, "application_index") | ||
|
||
raise(ArgumentError, "application not found") unless @application_index | ||
|
||
@application_index -= 1 # FindApplicationIndexQuery returns a index starting at 1 | ||
@application_index -= used_urns.size # removes the existing applications to have a correct index | ||
@application_index | ||
end | ||
|
||
def available_urns | ||
@available_urns ||= URNS.fetch(@application.application_route) - used_urns | ||
end | ||
|
||
def used_urns | ||
@used_urns ||= Application.where(application_route: @application.application_route).pluck(:urn) | ||
end | ||
|
||
MUTEX = Mutex.new | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe Application::Urn do | ||
describe "constants" do | ||
it { expect(described_class::LENGTH).to eq(99_999) } | ||
it { expect(described_class::PREFIX).to eq("IRP") } | ||
it { expect(described_class::URNS.keys).to contain_exactly("teacher", "salaried_trainee") } | ||
it { expect(described_class::URNS.dig("teacher", 1)).to include("IRPTE") } | ||
it { expect(described_class::URNS.fetch("teacher").size).to eq(99_998) } | ||
it { expect(described_class::URNS.dig("salaried_trainee", 1)).to include("IRPST") } | ||
it { expect(described_class::URNS.fetch("salaried_trainee").size).to eq(99_998) } | ||
end | ||
|
||
describe "urn" do | ||
subject(:service) { described_class.new(application) } | ||
|
||
context "teacher" do | ||
let(:application) { create(:teacher_application) } | ||
|
||
it { expect(service.urn).to include("IRPTE") } | ||
end | ||
|
||
context "salaried_trainee" do | ||
let(:application) { create(:salaried_trainee_application) } | ||
|
||
it { expect(service.urn).to include("IRPST") } | ||
end | ||
|
||
context "missing application" do | ||
let(:application) { build(:salaried_trainee_application) } | ||
|
||
it { expect { service.urn }.to raise_error(ArgumentError, "application not found") } | ||
end | ||
end | ||
end |