Skip to content

Commit 4bf4d3e

Browse files
committed
Split by Project ref to compute latest artifacts
1 parent e8ea26d commit 4bf4d3e

6 files changed

Lines changed: 63 additions & 29 deletions

File tree

modules/core/shared/src/main/scala/scaladex/core/service/WebDatabase.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ trait WebDatabase:
1414
artifactId: Artifact.ArtifactId,
1515
stableOnly: Boolean
1616
): Future[Seq[Version]]
17-
def getArtifacts(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]]
17+
def getArtifacts(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]]
1818
def getArtifact(ref: Artifact.Reference): Future[Option[Artifact]]
19-
def getLatestArtifact(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]]
19+
def getLatestArtifact(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]]
20+
// can return more than one artifact, if artifacts are split in several projects
21+
def getLatestArtifacts( groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]]
2022
def getAllArtifacts(language: Option[Language], platform: Option[Platform]): Future[Seq[Artifact]]
2123
def countArtifacts(): Future[Long]
2224

modules/core/shared/src/test/scala/scaladex/core/test/InMemoryDatabase.scala

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class InMemoryDatabase extends SchedulerDatabase:
1414
private val allProjects = mutable.Map[Project.Reference, Project]()
1515
private val allArtifacts = mutable.Map[Artifact.Reference, Artifact]()
1616
private val allDependencies = mutable.Buffer[ArtifactDependency]()
17-
private val latestArtifacts = mutable.Map[(Artifact.GroupId, Artifact.ArtifactId), Artifact.Reference]()
17+
private val latestArtifacts = mutable.Map[(Project.Reference, Artifact.GroupId, Artifact.ArtifactId), Artifact.Reference]()
1818

1919
def reset(): Unit =
2020
allProjects.clear()
@@ -52,8 +52,8 @@ class InMemoryDatabase extends SchedulerDatabase:
5252
override def getProject(projectRef: Project.Reference): Future[Option[Project]] =
5353
Future.successful(allProjects.get(projectRef))
5454

55-
override def getArtifacts(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
56-
val res = allArtifacts.values.filter(a => a.groupId == groupId && a.artifactId == artifactId).toSeq
55+
override def getArtifacts(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
56+
val res = allArtifacts.values.filter(a => a.projectRef == ref && a.groupId == groupId && a.artifactId == artifactId).toSeq
5757
Future.successful(res)
5858

5959
override def getAllProjectArtifacts(ref: Project.Reference): Future[Seq[Artifact]] =
@@ -195,7 +195,7 @@ class InMemoryDatabase extends SchedulerDatabase:
195195

196196
override def getProjectLatestArtifacts(ref: Project.Reference): Future[Seq[Artifact]] =
197197
val res = getProjectArtifactsSync(ref)
198-
.flatMap(a => latestArtifacts.get((a.groupId, a.artifactId)))
198+
.flatMap(a => latestArtifacts.get((ref, a.groupId, a.artifactId)))
199199
.distinct
200200
.map(allArtifacts.apply)
201201
Future.successful(res)
@@ -204,7 +204,7 @@ class InMemoryDatabase extends SchedulerDatabase:
204204
Future.successful(getProjectArtifactsSync(ref).map(a => (a.groupId, a.artifactId)).distinct.toSeq)
205205

206206
override def updateLatestVersion(ref: Project.Reference, artifact: Artifact.Reference): Future[Unit] =
207-
latestArtifacts += (artifact.groupId, artifact.artifactId) -> artifact
207+
latestArtifacts += (ref, artifact.groupId, artifact.artifactId) -> artifact
208208
Future.unit
209209

210210
override def getArtifactVersions(
@@ -217,6 +217,14 @@ class InMemoryDatabase extends SchedulerDatabase:
217217
}.toSeq
218218
Future.successful(res)
219219

220-
override def getLatestArtifact(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
221-
Future.successful(latestArtifacts.get((groupId, artifactId)).map(allArtifacts.apply))
220+
override def getLatestArtifact(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
221+
Future.successful(latestArtifacts.get((ref, groupId, artifactId)).map(allArtifacts.apply))
222+
223+
override def getLatestArtifacts(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
224+
val res = latestArtifacts
225+
.values
226+
.filter(a => a.groupId == groupId && a.artifactId == artifactId)
227+
.map(allArtifacts.apply)
228+
.toSeq
229+
Future.successful(res)
222230
end InMemoryDatabase

modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten
3333
): Future[Seq[Version]] =
3434
run(ArtifactTable.selectVersionByGroupIdAndArtifactId(stableOnly).to[Seq]((groupId, artifactId)))
3535

36-
override def getLatestArtifact(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
37-
run(ArtifactTable.selectLatestArtifact.option((groupId, artifactId)))
36+
override def getLatestArtifact(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
37+
run(ArtifactTable.selectLatestArtifact.option((ref, groupId, artifactId)))
38+
39+
override def getLatestArtifacts(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
40+
run(ArtifactTable.selectLatestArtifacts.to[Seq]((groupId, artifactId)))
3841

3942
override def insertArtifacts(artifacts: Seq[Artifact]): Future[Unit] =
4043
run(ArtifactTable.insertIfNotExist.updateMany(artifacts)).map(_ => ())
@@ -46,8 +49,8 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten
4649
override def updateArtifactReleaseDate(ref: Artifact.Reference, releaseDate: Instant): Future[Int] =
4750
run(ArtifactTable.updateReleaseDate.run((releaseDate, ref)))
4851

49-
override def getArtifacts(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
50-
run(ArtifactTable.selectArtifactByGroupIdAndArtifactId.to[Seq](groupId, artifactId))
52+
override def getArtifacts(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Seq[Artifact]] =
53+
run(ArtifactTable.selectArtifactByGroupIdAndArtifactId.to[Seq]((ref, groupId, artifactId)))
5154

5255
override def getArtifact(ref: Artifact.Reference): Future[Option[Artifact]] =
5356
run(ArtifactTable.selectByReference.option(ref))
@@ -129,7 +132,7 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten
129132

130133
private val projectLatestArtifactsCache: AsyncLoadingCache[Project.Reference, Seq[Artifact]] =
131134
// invalidated manually by updateLatestVersion
132-
Scaffeine().buildAsyncFuture(ref => run(ArtifactTable.selectLatestArtifacts.to[Seq](ref)))
135+
Scaffeine().buildAsyncFuture(ref => run(ArtifactTable.selectProjectLatestArtifacts.to[Seq](ref)))
133136
override def getProjectLatestArtifacts(ref: Project.Reference): Future[Seq[Artifact]] =
134137
projectLatestArtifactsCache.get(ref)
135138

@@ -218,8 +221,8 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten
218221

219222
override def updateLatestVersion(ref: Project.Reference, artifact: Artifact.Reference): Future[Unit] =
220223
val transaction = for
221-
_ <- ArtifactTable.setLatestVersion.run(artifact)
222-
_ <- ArtifactTable.unsetOthersLatestVersion.run(artifact)
224+
_ <- ArtifactTable.setLatestVersion.run((ref, artifact))
225+
_ <- ArtifactTable.unsetOthersLatestVersion.run((ref, artifact))
223226
yield ()
224227
run(transaction).map(_ => projectLatestArtifactsCache.underlying.synchronous().invalidate(ref))
225228

modules/infra/src/main/scala/scaladex/infra/sql/ArtifactTable.scala

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ object ArtifactTable:
5656
val where = language.map(v => s"language_version='${v.value}'").toSeq ++ platform.map(p => s"platform='${p.value}'")
5757
selectRequest(table, mainFields, where = where)
5858

59-
val selectArtifactByGroupIdAndArtifactId: Query[(GroupId, ArtifactId), Artifact] =
60-
selectRequest(table, mainFields, Seq("group_id", "artifact_id"))
59+
val selectArtifactByGroupIdAndArtifactId: Query[(Project.Reference, GroupId, ArtifactId), Artifact] =
60+
selectRequest(table, mainFields, Seq("organization", "repository", "group_id", "artifact_id"))
6161

6262
def selectVersionByGroupIdAndArtifactId(stableOnly: Boolean): Query[(GroupId, ArtifactId), Version] =
6363
selectRequest1(
@@ -67,8 +67,21 @@ object ArtifactTable:
6767
where = stableOnlyFilter(stableOnly).toSeq
6868
)
6969

70-
val selectLatestArtifact: Query[(GroupId, ArtifactId), Artifact] =
71-
selectRequest1(table, mainFields, keys = Seq("group_id", "artifact_id"), where = Seq("is_latest_version"))
70+
val selectLatestArtifact: Query[(Project.Reference, GroupId, ArtifactId), Artifact] =
71+
selectRequest1(
72+
table,
73+
mainFields,
74+
keys = Seq("organization", "repository", "group_id", "artifact_id"),
75+
where = Seq("is_latest_version")
76+
)
77+
78+
val selectLatestArtifacts: Query[(GroupId, ArtifactId), Artifact] =
79+
selectRequest1(
80+
table,
81+
mainFields,
82+
keys = Seq("group_id", "artifact_id"),
83+
where = Seq("is_latest_version")
84+
)
7285

7386
val selectArtifactByProject: Query[Project.Reference, Artifact] =
7487
selectRequest1(
@@ -147,16 +160,20 @@ object ArtifactTable:
147160
groupBy = projectReferenceFields
148161
)
149162

150-
def selectLatestArtifacts: Query[Project.Reference, Artifact] =
163+
def selectProjectLatestArtifacts: Query[Project.Reference, Artifact] =
151164
selectRequest1(table, mainFields, where = Seq("organization=?", "repository=?", "is_latest_version=true"))
152165

153-
def setLatestVersion: Update[Reference] =
154-
updateRequest0(table, set = Seq("is_latest_version=true"), where = Seq("group_id=?", "artifact_id=?", "version=?"))
166+
def setLatestVersion: Update[(Project.Reference, Reference)] =
167+
updateRequest0(
168+
table,
169+
set = Seq("is_latest_version=true"),
170+
where = Seq("organization=?", "repository=?", "group_id=?", "artifact_id=?", "version=?")
171+
)
155172

156-
def unsetOthersLatestVersion: Update[Reference] =
173+
def unsetOthersLatestVersion: Update[(Project.Reference, Reference)] =
157174
updateRequest0(
158175
table,
159176
set = Seq("is_latest_version=false"),
160-
where = Seq("group_id=?", "artifact_id=?", "version<>?")
177+
where = Seq("organization=?", "repository=?", "group_id=?", "artifact_id=?", "version<>?")
161178
)
162179
end ArtifactTable

modules/infra/src/test/scala/scaladex/infra/SqlDatabaseTests.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ class SqlDatabaseTests extends AsyncFunSpec with BaseDatabaseSuite with Matchers
291291
val artifacts = Seq(Cats.`core_2.13:2.5.0`, Cats.`core_3:2.6.1`)
292292
for
293293
_ <- database.insertArtifacts(artifacts)
294-
obtained1 <- database.getArtifacts(Cats.groupId, Artifact.ArtifactId("cats-core_3"))
295-
obtained2 <- database.getArtifacts(Cats.groupId, Artifact.ArtifactId("cats-core_2.13"))
294+
obtained1 <- database.getArtifacts(Cats.reference, Cats.groupId, Artifact.ArtifactId("cats-core_3"))
295+
obtained2 <- database.getArtifacts(Cats.reference, Cats.groupId, Artifact.ArtifactId("cats-core_2.13"))
296296
yield
297297
obtained1 should contain theSameElementsAs Seq(Cats.`core_3:2.6.1`)
298298
obtained2 should contain theSameElementsAs Seq(Cats.`core_2.13:2.5.0`)

modules/server/src/main/scala/scaladex/server/service/ArtifactService.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ class ArtifactService(database: SchedulerDatabase)(using ExecutionContext) exten
1919
): Future[Seq[Version]] =
2020
database.getArtifactVersions(groupId, artifactId, stableOnly)
2121

22+
def getLatestArtifact(ref: Project.Reference, groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
23+
database.getLatestArtifact(ref, groupId, artifactId)
24+
2225
def getLatestArtifact(groupId: Artifact.GroupId, artifactId: Artifact.ArtifactId): Future[Option[Artifact]] =
23-
database.getLatestArtifact(groupId, artifactId)
26+
database.getLatestArtifacts(groupId, artifactId)
27+
.map(artifacts => artifacts.maxOption(using Ordering.by(_.releaseDate)))
2428

2529
def getArtifact(ref: Artifact.Reference): Future[Option[Artifact]] =
2630
database.getArtifact(ref)
@@ -86,7 +90,7 @@ class ArtifactService(database: SchedulerDatabase)(using ExecutionContext) exten
8690
preferStableVersion: Boolean
8791
): Future[Unit] =
8892
for
89-
artifacts <- database.getArtifacts(groupId, artifactId)
93+
artifacts <- database.getArtifacts(ref, groupId, artifactId)
9094
latestVersion = computeLatestVersion(artifacts.map(_.version), preferStableVersion)
9195
_ <- database.updateLatestVersion(ref, Artifact.Reference(groupId, artifactId, latestVersion))
9296
yield ()

0 commit comments

Comments
 (0)