Skip to content

Commit

Permalink
Fixed broken data consumption logic due to missing bundleId in OcsEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
vihangpatil authored Aug 22, 2018
2 parents b642713 + a63442a commit d9c3a0c
Show file tree
Hide file tree
Showing 24 changed files with 88 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

[![Kotlin version badge](https://img.shields.io/badge/kotlin-1.2.60-blue.svg)](http://kotlinlang.org/)
[![Kotlin version badge](https://img.shields.io/badge/kotlin-1.2.61-blue.svg)](http://kotlinlang.org/)
[![Prime version](https://img.shields.io/github/tag/ostelco/ostelco-core.svg)](https://github.com/ostelco/ostelco-core/tags)
[![GitHub license](https://img.shields.io/github/license/ostelco/ostelco-core.svg)](https://github.com/ostelco/ostelco-core/blob/master/LICENSE)

Expand Down
2 changes: 1 addition & 1 deletion acceptance-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "application"
id "com.github.johnrengelman.shadow" version "2.0.4"
}
Expand Down
114 changes: 58 additions & 56 deletions acceptance-tests/src/main/kotlin/org/ostelco/at/pgw/OcsTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.ostelco.at.pgw

import org.jdiameter.api.Avp
import org.jdiameter.api.AvpDataException
import org.jdiameter.api.Session
import org.junit.After
import org.junit.Before
Expand All @@ -11,9 +10,12 @@ import org.ostelco.at.common.createProfile
import org.ostelco.at.common.createSubscription
import org.ostelco.at.common.logger
import org.ostelco.at.common.randomInt
import org.ostelco.at.jersey.get
import org.ostelco.diameter.model.RequestType
import org.ostelco.diameter.test.TestClient
import org.ostelco.diameter.test.TestHelper
import org.ostelco.prime.client.model.SubscriptionStatus
import java.lang.Thread.sleep
import kotlin.test.assertEquals
import kotlin.test.fail

Expand Down Expand Up @@ -57,22 +59,17 @@ class OcsTest {

waitForAnswer()

try {
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(RequestType.INITIAL_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).unsigned32)
assertEquals(10, resultMSCC.grouped.getAvp(Avp.RATING_GROUP).unsigned32)
val granted = resultMSCC.grouped.getAvp(Avp.GRANTED_SERVICE_UNIT)
assertEquals(BUCKET_SIZE, granted.grouped.getAvp(Avp.CC_TOTAL_OCTETS).unsigned64)
} catch (e: AvpDataException) {
logger.error("Failed to get Result-Code", e)
}

assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(RequestType.INITIAL_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).unsigned32)
assertEquals(10, resultMSCC.grouped.getAvp(Avp.RATING_GROUP).unsigned32)
val granted = resultMSCC.grouped.getAvp(Avp.GRANTED_SERVICE_UNIT)
assertEquals(BUCKET_SIZE, granted.grouped.getAvp(Avp.CC_TOTAL_OCTETS).unsigned64)
}

private fun simpleCreditControlRequestUpdate(session: Session) {
Expand All @@ -91,20 +88,25 @@ class OcsTest {

waitForAnswer()

try {
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
assertEquals(RequestType.UPDATE_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
val granted = resultMSCC.grouped.getAvp(Avp.GRANTED_SERVICE_UNIT)
assertEquals(BUCKET_SIZE, granted.grouped.getAvp(Avp.CC_TOTAL_OCTETS).unsigned64)
} catch (e: AvpDataException) {
logger.error("Failed to get Result-Code", e)
}
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
assertEquals(RequestType.UPDATE_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
val granted = resultMSCC.grouped.getAvp(Avp.GRANTED_SERVICE_UNIT)
assertEquals(BUCKET_SIZE, granted.grouped.getAvp(Avp.CC_TOTAL_OCTETS).unsigned64)
}

private fun getBalance(): Long {
sleep(200) // wait for 200 ms for balance to be updated in db

val subscriptionStatus: SubscriptionStatus = get {
path = "/subscription/status"
subscriberId = EMAIL
}
return subscriptionStatus.remaining
}

@Test
Expand All @@ -114,7 +116,10 @@ class OcsTest {

val session = client.createSession() ?: fail("Failed to create session")
simpleCreditControlRequestInit(session)
assertEquals(INITIAL_BALANCE - BUCKET_SIZE, getBalance(), message = "Incorrect balance after init")

simpleCreditControlRequestUpdate(session)
assertEquals(INITIAL_BALANCE - 2 * BUCKET_SIZE, getBalance(), message = "Incorrect balance after update")

val request = client.createRequest(
DEST_REALM,
Expand All @@ -128,22 +133,19 @@ class OcsTest {

waitForAnswer()

try {
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
assertEquals(RequestType.TERMINATION_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).unsigned32)
assertEquals(10, resultMSCC.grouped.getAvp(Avp.RATING_GROUP).unsigned32)
val validTime = resultMSCC.grouped.getAvp(Avp.VALIDITY_TIME)
assertEquals(86400L, validTime.unsigned32)
} catch (e: AvpDataException) {
logger.error("Failed to get Result-Code", e)
}

assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
assertEquals(DEST_REALM, resultAvps.getAvp(Avp.ORIGIN_REALM).utF8String)
assertEquals(RequestType.TERMINATION_REQUEST.toLong(), resultAvps.getAvp(Avp.CC_REQUEST_TYPE).integer32.toLong())
val resultMSCC = resultAvps.getAvp(Avp.MULTIPLE_SERVICES_CREDIT_CONTROL)
assertEquals(2001L, resultMSCC.grouped.getAvp(Avp.RESULT_CODE).integer32.toLong())
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).unsigned32)
assertEquals(10, resultMSCC.grouped.getAvp(Avp.RATING_GROUP).unsigned32)
val validTime = resultMSCC.grouped.getAvp(Avp.VALIDITY_TIME)
assertEquals(86400L, validTime.unsigned32)

assertEquals(INITIAL_BALANCE - 2 * BUCKET_SIZE, getBalance(), message = "Incorrect balance after terminate")
}


Expand All @@ -165,7 +167,7 @@ class OcsTest {

waitForAnswer()

try {
run {
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
Expand All @@ -176,12 +178,11 @@ class OcsTest {
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).integer32.toLong())
val granted = resultMSCC.grouped.getAvp(Avp.GRANTED_SERVICE_UNIT)
assertEquals(0L, granted.grouped.getAvp(Avp.CC_TOTAL_OCTETS).unsigned64)
} catch (e: AvpDataException) {
logger.error("Failed to get Result-Code", e)
}

// There is 2 step in graceful shutdown. First OCS send terminate, then P-GW report used units in a final update

assertEquals(INITIAL_BALANCE, getBalance(), message = "Incorrect balance after init using wrong msisdn")

val updateRequest = client.createRequest(
DEST_REALM,
DEST_HOST,
Expand All @@ -194,7 +195,7 @@ class OcsTest {

waitForAnswer()

try {
run {
assertEquals(2001L, client.resultCodeAvp?.integer32?.toLong())
val resultAvps = client.resultAvps ?: fail("Missing AVPs")
assertEquals(DEST_HOST, resultAvps.getAvp(Avp.ORIGIN_HOST).utF8String)
Expand All @@ -205,10 +206,9 @@ class OcsTest {
assertEquals(1, resultMSCC.grouped.getAvp(Avp.SERVICE_IDENTIFIER_CCA).integer32.toLong())
val validTime = resultMSCC.grouped.getAvp(Avp.VALIDITY_TIME)
assertEquals(86400L, validTime.unsigned32)
} catch (e: AvpDataException) {
logger.error("Failed to get Result-Code", e)
}

assertEquals(INITIAL_BALANCE, getBalance(), message = "Incorrect balance after update using wrong msisdn")
}


Expand All @@ -234,18 +234,20 @@ class OcsTest {
private const val DEST_REALM = "loltel"
private const val DEST_HOST = "ocs"

private const val INITIAL_BALANCE = 100_000_000L
private const val BUCKET_SIZE = 500L

private lateinit var EMAIL: String
private lateinit var MSISDN: String

@BeforeClass
@JvmStatic
fun createTestUserAndSubscription() {

val email = "ocs-${randomInt()}@test.com"
createProfile(name = "Test OCS User", email = email)
EMAIL = "ocs-${randomInt()}@test.com"
createProfile(name = "Test OCS User", email = EMAIL)

MSISDN = createSubscription(email)
MSISDN = createSubscription(EMAIL)
}
}
}
2 changes: 1 addition & 1 deletion admin-api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion analytics/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "application"
id "com.github.johnrengelman.shadow" version "2.0.4"
id "idea"
Expand Down
2 changes: 1 addition & 1 deletion app-notifier/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion auth-server/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "application"
id "com.github.johnrengelman.shadow" version "2.0.4"
id "idea"
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ subprojects {
options.encoding = 'UTF-8'
}
ext {
kotlinVersion = "1.2.60"
kotlinVersion = "1.2.61"
dropwizardVersion = "1.3.5"
googleCloudVersion = "1.35.0"
jacksonVersion = "2.9.6"
Expand Down
2 changes: 1 addition & 1 deletion client-api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion diameter-stack/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
id "signing"
id "maven"
Expand Down
2 changes: 1 addition & 1 deletion diameter-test/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
id "signing"
id "maven"
Expand Down
2 changes: 1 addition & 1 deletion ext-auth-provider/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "application"
id "com.github.johnrengelman.shadow" version "2.0.4"
}
Expand Down
2 changes: 1 addition & 1 deletion firebase-store/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion model/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion neo4j-store/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion ocs/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.ostelco.prime.events
import com.lmax.disruptor.EventHandler
import org.ostelco.prime.disruptor.EventMessageType.CREDIT_CONTROL_REQUEST
import org.ostelco.prime.disruptor.EventMessageType.RELEASE_RESERVED_BUCKET
import org.ostelco.prime.disruptor.EventMessageType.REMOVE_MSISDN_TO_BUNDLE_MAPPING
import org.ostelco.prime.disruptor.EventMessageType.TOPUP_DATA_BUNDLE_BALANCE
import org.ostelco.prime.disruptor.OcsEvent
import org.ostelco.prime.logger
Expand All @@ -28,7 +29,8 @@ class EventProcessor(
try {
if (event.messageType == CREDIT_CONTROL_REQUEST
|| event.messageType == RELEASE_RESERVED_BUCKET
|| event.messageType == TOPUP_DATA_BUNDLE_BALANCE) {
|| event.messageType == TOPUP_DATA_BUNDLE_BALANCE
|| event.messageType == REMOVE_MSISDN_TO_BUNDLE_MAPPING) {
logger.info("Updating data bundle balance for {} : {} to {} bytes",
event.msisdn, event.bundleId, event.bundleBytes)
val bundleId = event.bundleId
Expand Down
8 changes: 6 additions & 2 deletions ocs/src/main/kotlin/org/ostelco/prime/ocs/OcsState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class OcsState(val loadSubscriberInfo:Boolean = true) : EventHandler<OcsEvent> {
event.reservedBucketBytes = reserveDataBytes(
msisdn,
event.requestedBucketBytes)
event.bundleBytes = getDataBundleBytes(msisdn = msisdn)
event.bundleId = msisdnToBundleIdMap[msisdn]
event.bundleBytes = bundleBalanceMap[event.bundleId] ?: 0
}
TOPUP_DATA_BUNDLE_BALANCE -> {
val bundleId = event.bundleId
Expand All @@ -63,6 +64,8 @@ class OcsState(val loadSubscriberInfo:Boolean = true) : EventHandler<OcsEvent> {
return
}
releaseReservedBucket(msisdn = msisdn)
event.bundleId = msisdnToBundleIdMap[msisdn]
event.bundleBytes = bundleBalanceMap[event.bundleId] ?: 0
}
UPDATE_BUNDLE -> {
val bundleId = event.bundleId
Expand Down Expand Up @@ -98,9 +101,10 @@ class OcsState(val loadSubscriberInfo:Boolean = true) : EventHandler<OcsEvent> {
logger.error("Received null as bundleId")
return
}
releaseReservedBucket(msisdn = msisdn)
event.bundleBytes = bundleBalanceMap[bundleId] ?: 0
msisdnToBundleIdMap.remove(msisdn)
bundleIdToMsisdnMap[bundleId]?.remove(msisdn)
// TODO vihang: return reserved bytes back to bundle
}
}
} catch (e: Exception) {
Expand Down
2 changes: 1 addition & 1 deletion payment-processor/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
id "idea"
}
Expand Down
2 changes: 1 addition & 1 deletion prime-api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "java-library"
}

Expand Down
2 changes: 1 addition & 1 deletion prime-client-api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id 'java-library'
id 'org.hidetake.swagger.generator' version '2.12.0'
id "idea"
Expand Down
2 changes: 1 addition & 1 deletion prime/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.60"
id "org.jetbrains.kotlin.jvm" version "1.2.61"
id "application"
id "com.github.johnrengelman.shadow" version "2.0.4"
id "idea"
Expand Down
Loading

0 comments on commit d9c3a0c

Please sign in to comment.