|
|
@@ -5,28 +5,36 @@ import {
|
|
|
StartQueryExecutionCommand,
|
|
|
type Row,
|
|
|
} from "@aws-sdk/client-athena"
|
|
|
-import { Effect, Layer, Schema } from "effect"
|
|
|
+import { Effect, Layer } from "effect"
|
|
|
import * as Context from "effect/Context"
|
|
|
import { Resource } from "sst/resource"
|
|
|
|
|
|
-const ATHENA_MAX_POLL_ATTEMPTS = 60
|
|
|
+const ATHENA_MAX_POLL_ATTEMPTS = 300
|
|
|
const ATHENA_PAGE_SIZE = 1000
|
|
|
|
|
|
export type AthenaData = Record<string, string>
|
|
|
|
|
|
-export class AthenaQueryError extends Schema.TaggedErrorClass<AthenaQueryError>()("AthenaQueryError", {
|
|
|
- message: Schema.String,
|
|
|
- queryExecutionId: Schema.optional(Schema.String),
|
|
|
- cause: Schema.optional(Schema.Defect()),
|
|
|
-}) {}
|
|
|
+export class AthenaQueryError extends Error {
|
|
|
+ readonly _tag = "AthenaQueryError"
|
|
|
+ readonly queryExecutionId?: string
|
|
|
|
|
|
-export class AthenaQueryTimeoutError extends Schema.TaggedErrorClass<AthenaQueryTimeoutError>()(
|
|
|
- "AthenaQueryTimeoutError",
|
|
|
- {
|
|
|
- message: Schema.String,
|
|
|
- queryExecutionId: Schema.String,
|
|
|
- },
|
|
|
-) {}
|
|
|
+ constructor(input: { message: string; queryExecutionId?: string; cause?: unknown }) {
|
|
|
+ super(input.message, { cause: input.cause })
|
|
|
+ this.name = "AthenaQueryError"
|
|
|
+ this.queryExecutionId = input.queryExecutionId
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export class AthenaQueryTimeoutError extends Error {
|
|
|
+ readonly _tag = "AthenaQueryTimeoutError"
|
|
|
+ readonly queryExecutionId: string
|
|
|
+
|
|
|
+ constructor(input: { message: string; queryExecutionId: string }) {
|
|
|
+ super(input.message)
|
|
|
+ this.name = "AthenaQueryTimeoutError"
|
|
|
+ this.queryExecutionId = input.queryExecutionId
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
export declare namespace Athena {
|
|
|
export interface Service {
|
|
|
@@ -57,7 +65,7 @@ export class Athena extends Context.Service<Athena, Athena.Service>()("@opencode
|
|
|
})
|
|
|
const queryExecutionId = started.QueryExecutionId
|
|
|
if (!queryExecutionId)
|
|
|
- return yield* new AthenaQueryError({ message: "Athena did not return a query execution id" })
|
|
|
+ return yield* Effect.fail(new AthenaQueryError({ message: "Athena did not return a query execution id" }))
|
|
|
|
|
|
yield* poll(client, queryExecutionId)
|
|
|
return yield* results(client, queryExecutionId)
|
|
|
@@ -87,16 +95,20 @@ const poll: (
|
|
|
|
|
|
if (status?.State === "SUCCEEDED") return
|
|
|
if (status?.State === "FAILED" || status?.State === "CANCELLED")
|
|
|
- return yield* new AthenaQueryError({
|
|
|
- message: `Athena stats query ${status.State.toLowerCase()}: ${status.StateChangeReason ?? "unknown reason"}`,
|
|
|
- queryExecutionId,
|
|
|
- })
|
|
|
+ return yield* Effect.fail(
|
|
|
+ new AthenaQueryError({
|
|
|
+ message: `Athena stats query ${status.State.toLowerCase()}: ${status.StateChangeReason ?? "unknown reason"}`,
|
|
|
+ queryExecutionId,
|
|
|
+ }),
|
|
|
+ )
|
|
|
|
|
|
if (attempt >= ATHENA_MAX_POLL_ATTEMPTS - 1)
|
|
|
- return yield* new AthenaQueryTimeoutError({
|
|
|
- message: `Athena stats query ${queryExecutionId} did not complete`,
|
|
|
- queryExecutionId,
|
|
|
- })
|
|
|
+ return yield* Effect.fail(
|
|
|
+ new AthenaQueryTimeoutError({
|
|
|
+ message: `Athena stats query ${queryExecutionId} did not complete`,
|
|
|
+ queryExecutionId,
|
|
|
+ }),
|
|
|
+ )
|
|
|
|
|
|
return yield* poll(client, queryExecutionId, attempt + 1)
|
|
|
})
|