Reserve number in appropriate backend

Amolith created

- At the start of registration, numbers are now reserved in
  Bandwidth or "reserved" in the local inventory, whichever source the
  number is from
- Tests mock successful reservation rather than half of a reservation

Signed-off-by: Amolith <amolith@secluded.site>

Change summary

lib/registration.rb       | 17 +++++++++++++++--
lib/tel_selections.rb     |  8 ++++++++
test/test_helper.rb       |  5 +++++
test/test_registration.rb | 17 +++++++++++++++++
4 files changed, 45 insertions(+), 2 deletions(-)

Detailed changes

lib/registration.rb 🔗

@@ -22,12 +22,25 @@ class Registration
 			Registered.for(customer, reg.phone)
 		else
 			tel_selections[customer.jid].then(&:choose_tel).then do |tel|
-				BandwidthTnReservationRepo.new.ensure(customer, tel)
-				FinishOrStartActivation.for(customer, google_play_userid, tel)
+				reserve_and_continue(tel_selections, customer, tel).then do
+					FinishOrStartActivation.for(customer, google_play_userid, tel)
+				end
 			end
 		end
 	end
 
+	def self.reserve_and_continue(tel_selections, customer, tel)
+		tel.reserve(customer).catch do
+			tel_selections.delete(customer.jid).then {
+				tel_selections[customer.jid]
+			}.then { |choose|
+				choose.choose_tel(
+					error: "The JMP number #{tel} is no longer available."
+				)
+			}.then { |n_tel| reserve_and_continue(tel_selections, customer, n_tel) }
+		end
+	end
+
 	class Registered
 		def self.for(customer, tel)
 			jid = ProxiedJID.new(customer.jid).unproxied

lib/tel_selections.rb 🔗

@@ -258,12 +258,20 @@ class TelSelections
 				def pending_value
 					tel
 				end
+
+				def reserve(customer)
+					BandwidthTnReservationRepo.new.ensure(customer, tel)
+				end
 			end
 
 			class LocalInventory < SimpleDelegator
 				def pending_value
 					"LocalInventory/#{tel}"
 				end
+
+				def reserve(*)
+					EMPromise.resolve(nil)
+				end
 			end
 		end
 

test/test_helper.rb 🔗

@@ -242,6 +242,11 @@ class FakeRedis
 		set(key, value)
 	end
 
+	def del(key)
+		@values.delete(key)
+		EMPromise.resolve("OK")
+	end
+
 	def mget(*keys)
 		EMPromise.all(keys.map(&method(:get)))
 	end

test/test_registration.rb 🔗

@@ -28,7 +28,24 @@ class RegistrationTest < Minitest::Test
 		reservation_req = stub_request(
 			:post,
 			"https://dashboard.bandwidth.com/v1.0/accounts//tnreservation"
+		).to_return(
+			status: 201,
+			headers: {
+				location: "https://dashboard.bandwidth.com/api/accounts//TnReservation/8da0f39c-043c-4806-9f0f-497b2d197bc5"
+			}
 		)
+		stub_request(
+			:get, "https://dashboard.bandwidth.com/v1.0/accounts//tnreservation/8da0f39c-043c-4806-9f0f-497b2d197bc5"
+		).to_return(status: 200, body: <<~RESPONSE)
+			<ReservationResponse>
+				<Reservation>
+					<ReservationId>f342904f-b03a-4499-bac0-e8f43a2664a1</ReservationId>
+					<AccountId>12346099</AccountId>
+					<ReservationExpires>1492</ReservationExpires>
+					<ReservedTn>4354776010</ReservedTn>
+				</Reservation>
+			</ReservationResponse>
+		RESPONSE
 		web_manager = TelSelections.new(
 			redis: FakeRedis.new, db: FakeDB.new, memcache: FakeMemcache.new
 		)