Skip to content

Commit

Permalink
supporting ordering of results in feature history
Browse files Browse the repository at this point in the history
  • Loading branch information
rvowles committed May 19, 2024
1 parent 1ef871c commit adc41d2
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 9 deletions.
9 changes: 9 additions & 0 deletions backend/mr-api/feature-history.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,17 @@ paths:
schema:
type: integer
description: "what position in the results to start at"
- name: order
in: query
schema:
$ref: "#/components/schemas/FeatureHistoryOrder"
components:
schemas:
FeatureHistoryOrder:
type: string
enum:
- asc
- desc
FeatureHistoryItem:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,14 @@ import io.featurehub.mr.model.FeatureHistoryList
import java.util.*

interface FeatureHistoryApi {
fun listHistory(appId: UUID, environmentIds: List<UUID>, versions: List<Long>, keys: List<String>, featureIds: List<UUID>, max: Int?, startAt: Int?): FeatureHistoryList
fun listHistory(
appId: UUID,
environmentIds: List<UUID>,
versions: List<Long>,
keys: List<String>,
featureIds: List<UUID>,
max: Int?,
startAt: Int?,
orderDescending: Boolean
): FeatureHistoryList
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class FeatureHistorySqlApi : InternalFeatureHistoryApi, FeatureHistoryApi {
keys: List<String>,
featureIds: List<UUID>,
max: Int?,
startAt: Int?
startAt: Int?,
orderDescending: Boolean
): FeatureHistoryList {
val highest = ((max ?: 20).coerceAtLeast(1)).coerceAtMost(100)
val start = (startAt?.coerceAtLeast(0) ?: 0)
Expand Down Expand Up @@ -60,7 +61,15 @@ class FeatureHistorySqlApi : InternalFeatureHistoryApi, FeatureHistoryApi {
}

val count = finder.findFutureCount()
val data = finder.setMaxRows(highest).setFirstRow(start).orderBy().id.version.asc().findList()
finder = finder.setMaxRows(highest).setFirstRow(start)

if (orderDescending) {
finder = finder.orderBy().id.version.desc()
} else {
finder = finder.orderBy().id.version.asc()
}

val data = finder.findList()

val items = mutableMapOf<FeatureHistoryItem, FeatureHistoryItem>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class FeatureHistorySpec extends Base3Spec {
and:
def historyApi = new FeatureHistorySqlApi()
when: "i ask for version history for all environments"
def result = historyApi.listHistory(app1.id, [env1.id, env2.id, env3.id], [], [], [], null, null)
def result = historyApi.listHistory(app1.id, [env1.id, env2.id, env3.id], [], [], [], null, null, false)
then:
result.max == 9
result.items.size() == 9
Expand All @@ -38,7 +38,7 @@ class FeatureHistorySpec extends Base3Spec {
def fv = featureSqlApi.getFeatureValueForEnvironment(env1.id, features[1].key)
featureSqlApi.updateFeatureValueForEnvironment(env1.id, features[1].key, fv.valueBoolean(true).locked(false), new PersonFeaturePermission(superPerson,
[RoleType.CHANGE_VALUE, RoleType.UNLOCK] as Set<RoleType>))
def result2 = historyApi.listHistory(app1.id, [env1.id], [], [], [features[1].id], null, null)
def result2 = historyApi.listHistory(app1.id, [env1.id], [], [], [features[1].id], null, null, false)
then:
result2.max == 2
result2.items.size() == 1
Expand All @@ -49,18 +49,22 @@ class FeatureHistorySpec extends Base3Spec {
result2.items[0].history[1].value
result2.items[0].history[1].who.id == superPerson.id.id
result2.items[0].history[1].who.name == superPerson.name
when: "i do the same query but reverse the order..."
def result2Rev = historyApi.listHistory(app1.id, [env1.id], [], [], [features[1].id], null, null, true)
then:
result2Rev.max == 2
when: "i update the first number and I see a single number version"
def num = featureSqlApi.getFeatureValueForEnvironment(env2.id, features[3].key)
featureSqlApi.updateFeatureValueForEnvironment(env2.id, features[3].key, fv.valueNumber(45.32).locked(false), new PersonFeaturePermission(superPerson,
[RoleType.CHANGE_VALUE, RoleType.UNLOCK] as Set<RoleType>))
def result3 = historyApi.listHistory(app1.id, [env2.id], [], [features[3].key], [], null, null)
def result3 = historyApi.listHistory(app1.id, [env2.id], [], [features[3].key], [], null, null, false)
then:
result3.max == 1
result3.items.size() == 1
result3.items[0].history.size() == 1
result3.items[0].history[0].value == 45.32
when: "i use an app id that doesn't relate to the features"
def result4 = historyApi.listHistory(UUID.randomUUID(), [env2.id], [], [features[3].key], [], null, null)
def result4 = historyApi.listHistory(UUID.randomUUID(), [env2.id], [], [features[3].key], [], null, null, false)
then:
result4.max == 0
result4.items.size() == 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import io.featurehub.db.api.FeatureHistoryApi
import io.featurehub.mr.api.FeatureHistoryServiceDelegate
import io.featurehub.mr.auth.AuthManagerService
import io.featurehub.mr.model.FeatureHistoryList
import io.featurehub.mr.model.FeatureHistoryOrder
import jakarta.inject.Inject
import jakarta.ws.rs.ForbiddenException
import jakarta.ws.rs.NotFoundException
import jakarta.ws.rs.core.SecurityContext
import java.util.*
Expand Down Expand Up @@ -35,6 +35,6 @@ class FeatureHistoryResource @Inject constructor(private val authManager: AuthMa

return featureHistoryApi.listHistory(appId, envs, holder.versions ?: listOf(),
holder.featureKeys ?: listOf(), holder.featureIds ?: listOf(),
holder.max, holder.startAt)
holder.max, holder.startAt, holder.order == FeatureHistoryOrder.DESC)
}
}
12 changes: 12 additions & 0 deletions infra/api-bucket/files/mrapi/1.2.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3275,6 +3275,13 @@ paths:
explode: true
schema:
type: integer
- name: order
in: query
required: false
style: form
explode: true
schema:
$ref: '#/components/schemas/FeatureHistoryOrder'
responses:
"200":
description: the webhook type details
Expand Down Expand Up @@ -5725,6 +5732,11 @@ components:
description: "Any configuration to pass to the check, e.g. webhook.feature.url,\
\ headers, etc - this ensures the updates get to the destination and are\
\ used. They get merged info the envInfo, replacing anything there"
FeatureHistoryOrder:
type: string
enum:
- asc
- desc
FeatureHistoryItem:
type: object
properties:
Expand Down

0 comments on commit adc41d2

Please sign in to comment.