-
Notifications
You must be signed in to change notification settings - Fork 1
#247 Implement basics of FlowReader #306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b97b603
e623974
5e4eadb
2e1e2ea
738c904
df8c9bd
5affd82
0f1e121
d773a93
0776f9c
38fde1c
1ac2233
e6dcb52
6968b02
b9bacef
bbb1e7f
33e6628
f7ced56
ca2116b
e5e6f63
fe07272
7656f6f
eb9a678
7641c07
bc82a5b
0e7675e
432716a
11b0a16
2c3f145
e07dffb
3955a50
b287a66
d04d23b
c344249
c0b0988
b53ba99
55d60e1
5dfe5c5
67ffe07
09e2ed8
e7ff732
e63a2e4
1488d1f
96ffa33
8b69e3e
04b56bd
698b765
855a333
be90711
afd64a6
f70143e
f803ea3
1a56f3d
bbed1f0
15dd12a
c630fa0
f4ce4d3
56cfa09
205952e
59a0b48
9bad58f
6b09086
383b532
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0" version="24.8.6"> | ||
| <diagram name="Page-1" id="M1M2r3vxqz2qx0Wid1ZL"> | ||
| <mxGraphModel dx="1434" dy="733" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> | ||
| <root> | ||
| <mxCell id="0" /> | ||
| <mxCell id="1" parent="0" /> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-1" value="PartitioningReader" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
| <mxGeometry x="440" y="40" width="120" height="60" as="geometry" /> | ||
| </mxCell> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-2" value="FlowReader" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
| <mxGeometry x="60" y="40" width="120" height="60" as="geometry" /> | ||
| </mxCell> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-4" value="<div align="left"><ul><li><b>Identified by the main paritioining</b></li><li>ability to retrieve <i>id_flow</i> based on the main partitioing <br></li><li>Getting the checkpoints belonging to the flow</li><li>Getting checkpoints of certain name only</li><li>Getting it's partitioning (phase 2)</li></ul></div>" style="rounded=0;whiteSpace=wrap;html=1;align=left;" vertex="1" parent="1"> | ||
| <mxGeometry x="80" y="110" width="240" height="160" as="geometry" /> | ||
| </mxCell> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-5" value="<div align="left">Data returned<ul><li>Checkpoints including partitioiing info in form of DTOs</li><li>returns just the dto as pagination</li></ul></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
| <mxGeometry x="80" y="310" width="250" height="130" as="geometry" /> | ||
| </mxCell> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-7" value="<blockquote><div align="left"><li><b>Identified by the paritioining</b></li></div><div align="left"><li>ability to retrieve <i>id_partitioing</i> based on the partitioing </li><li>Getting the checkpoints</li><li>Getting checkpoint(s) filtered by name</li><li>Getting the additional data</li><li>Getting the checkpoints + additional data in form of _INFO file format (phase 2)</li></div></blockquote>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
| <mxGeometry x="440" y="110" width="240" height="160" as="geometry" /> | ||
| </mxCell> | ||
| <mxCell id="rmWetNVkiCoe2Ea992-S-8" value="<div align="left">Data returned<ul><li>Checkpoints in the form of DTO in Pagination DTO</li><li>additional data as their DTO</li></ul></div>" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1"> | ||
| <mxGeometry x="440" y="320" width="240" height="120" as="geometry" /> | ||
| </mxCell> | ||
| </root> | ||
| </mxGraphModel> | ||
| </diagram> | ||
| </mxfile> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,21 +18,79 @@ package za.co.absa.atum.reader | |
|
|
||
| import sttp.client3.SttpBackend | ||
| import sttp.monad.MonadError | ||
| import sttp.monad.syntax._ | ||
| import za.co.absa.atum.model.dto.{CheckpointWithPartitioningDTO, FlowDTO} | ||
| import za.co.absa.atum.model.envelopes.SuccessResponse.{PaginatedResponse, SingleSuccessResponse} | ||
| import za.co.absa.atum.model.types.basic.AtumPartitions | ||
| import za.co.absa.atum.reader.basic.{PartitioningIdProvider, Reader} | ||
| import za.co.absa.atum.reader.core.RequestResult.RequestResult | ||
| import za.co.absa.atum.model.ApiPaths._ | ||
| import za.co.absa.atum.reader.core.{PartitioningIdProvider, Reader} | ||
| import za.co.absa.atum.reader.requests.QueryParamNames | ||
| import za.co.absa.atum.reader.server.ServerConfig | ||
|
|
||
| /** | ||
salamonpavel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * This class is a reader that reads data tight to a flow. | ||
| * @param mainFlowPartitioning - the partitioning of the main flow; renamed from ancestor's 'flowPartitioning' | ||
| * @param serverConfig - the Atum server configuration | ||
| * @param backend - sttp backend, that will be executing the requests | ||
| * @param ev - using evidence based approach to ensure that the type F is a MonadError instead of using context | ||
| * bounds, as it make the imports easier to follow | ||
| * @tparam F - the effect type (e.g. Future, IO, Task, etc.) | ||
| * | ||
| * @param mainFlowPartitioning - the partitioning of the main flow; renamed from ancestor's 'flowPartitioning' | ||
| * @param serverConfig - the Atum server configuration | ||
| * @param backend - sttp backend, that will be executing the requests | ||
| * @tparam F - the effect type (e.g. Future, IO, Task, etc.) | ||
| */ | ||
| class FlowReader[F[_]](val mainFlowPartitioning: AtumPartitions) | ||
| (implicit serverConfig: ServerConfig, backend: SttpBackend[F, Any], ev: MonadError[F]) | ||
| extends Reader[F] with PartitioningIdProvider[F]{ | ||
| case class FlowReader[F[_]: MonadError](mainFlowPartitioning: AtumPartitions) | ||
| (implicit serverConfig: ServerConfig, backend: SttpBackend[F, Any]) | ||
| extends Reader[F] with PartitioningIdProvider[F] { | ||
|
|
||
| /** | ||
| * Function to retrieve a page of checkpoints belonging to the flow. | ||
| * The checkpoints are ordered by their creation order. | ||
| * | ||
| * @param pageSize - the size of the page (record count) to be returned | ||
| * @param offset - offset of the page (starting position) | ||
| * @return - a page of checkpoints | ||
| */ | ||
| def getCheckpointsPage(pageSize: Int = 10, offset: Long = 0): F[RequestResult[PaginatedResponse[CheckpointWithPartitioningDTO]]] = { | ||
| for { | ||
| mainPartitioningIdOrError <- partitioningId(mainFlowPartitioning) | ||
| flowIdOrError <- mapRequestResultF(mainPartitioningIdOrError, queryFlowId) | ||
| checkpointsOrError <- mapRequestResultF(flowIdOrError, queryCheckpoints(_, None, pageSize, offset)) | ||
| } yield checkpointsOrError | ||
| } | ||
|
|
||
| /** | ||
| * Function to retrieve a page of checkpoints of the given name belonging to the flow. | ||
| * The checkpoints are ordered by their creation order. | ||
| * | ||
| * @param checkpointName - the name to filter with | ||
| * @param pageSize - the size of the page (record count) to be returned | ||
| * @param offset - offset of the page (starting position) | ||
| * @return - a page of checkpoints | ||
| */ | ||
| def getCheckpointsOfNamePage(checkpointName: String, pageSize: Int = 10, offset: Long = 0): F[RequestResult[PaginatedResponse[CheckpointWithPartitioningDTO]]] = { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not to have just 1 function with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see it as inconvenient call.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see it as: little convenience for users, little duplicity for developers. Less # of APIs & less code: better :D But I don't mind, it's a matter of style, if you want to keep it I'm definitely okay with it |
||
| for { | ||
| mainPartitioningIdOrError <- partitioningId(mainFlowPartitioning) | ||
| flowIdOrError <- mapRequestResultF(mainPartitioningIdOrError, queryFlowId) | ||
| checkpointsOrError <- mapRequestResultF(flowIdOrError, queryCheckpoints(_, Some(checkpointName), pageSize, offset)) | ||
| } yield checkpointsOrError | ||
| } | ||
|
|
||
| private def queryFlowId(mainPartitioningId: Long): F[RequestResult[Long]] = { | ||
| val endpoint = s"/$Api/$V2/${V2Paths.Partitionings}/$mainPartitioningId/${V2Paths.MainFlow}" | ||
| val queryResult = getQuery[SingleSuccessResponse[FlowDTO]](endpoint) | ||
| queryResult.map { result => | ||
| result.map(_.data.id) | ||
| } | ||
| } | ||
|
|
||
| private def queryCheckpoints(flowId: Long, | ||
salamonpavel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| checkpointName: Option[String], | ||
| limit: Int, | ||
| offset: Long): F[RequestResult[PaginatedResponse[CheckpointWithPartitioningDTO]]] = { | ||
| val endpoint = s"/$Api/$V2/${V2Paths.Flows}/$flowId/${V2Paths.Checkpoints}" | ||
| val params = Map( | ||
| QueryParamNames.Limit -> limit.toString, | ||
| QueryParamNames.Offset -> offset.toString | ||
| ) ++ checkpointName.map(QueryParamNames.CheckpointName -> _) | ||
| getQuery(endpoint, params) | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| /* | ||
| * Copyright 2021 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package za.co.absa.atum.reader.exceptions | ||
|
|
||
| class ReaderException(message: String) extends Exception(message) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* | ||
| * Copyright 2021 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package za.co.absa.atum.reader.exceptions | ||
|
|
||
| import sttp.model.{StatusCode, Uri} | ||
| import za.co.absa.atum.model.envelopes.ErrorResponse | ||
|
|
||
| sealed abstract class RequestException(message: String) extends ReaderException(message) | ||
|
|
||
|
|
||
| object RequestException { | ||
salamonpavel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| type CirceError = io.circe.Error | ||
|
|
||
| final case class HttpException( | ||
| message: String, | ||
| statusCode: StatusCode, | ||
| errorResponse: ErrorResponse, | ||
| request: Uri | ||
| ) extends RequestException(message) | ||
|
|
||
| final case class ParsingException( | ||
| message: String, | ||
| body: String | ||
| ) extends RequestException(message) | ||
|
|
||
| object ParsingException { | ||
| def fromCirceError(error: CirceError, body: String): ParsingException = { | ||
| ParsingException(error.getMessage, body) | ||
| } | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /* | ||
| * Copyright 2021 ABSA Group Limited | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package za.co.absa.atum.reader.requests | ||
|
|
||
| object QueryParamNames { | ||
| final val Limit = "limit" | ||
| final val Offset = "offset" | ||
| final val CheckpointName = "checkpoint-name" | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.