我正在尝试使用Scala-Spark从数据源读取增量数据。在访问源表之前,我试图计算在将来的代码中使用的分区列的最小值和最大值,该列存在于以下类中:GetSourceMeta
。
def getBounds(keyIdMap:scala.collection.mutable.Map[String, String]): Future[scala.collection.mutable.Map[String, String]] = Future {
var boundsMap = scala.collection.mutable.Map[String, String]()
keyIdMap.keys.foreach(table => if(!keyIdMap(table).contains("Invalid")) {
val minMax = s"select max(insert_tms) maxTms, min(insert_tms) minTms from schema.${table} where source='DB2' and key_id in (${keyIdMap(table)})"
println("MinMax: " + minMax)
val boundsDF = spark.read.format("jdbc").option("url", con.getConUrl()).option("dbtable", s"(${minMax}) as ctids").option("user", con.getUserName()).option("password", con.getPwd()).load()
try {
val maxTms = boundsDF.select("minTms").head.getTimestamp(0).toString + "," + boundsDF.select("maxTms").head.getTimestamp(0).toString
println("Bounds: " + maxTms)
boundsMap += (table -> maxTms)
} catch {
case np: java.lang.NullPointerException => { println("No data found") }
case e: Exception => { println(s"Unknown exception: $e") }
}
}
)
boundsMap.foreach(println)
boundsMap
}
我在我的主要方法中将上述方法称为:
object LoadToCopyDB {
val conf = new SparkConf().setAppName("TEST_YEAR").set("some parameters")
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().config(conf).master("yarn").enableHiveSupport().config("hive.exec.dynamic.partition", "true").config("hive.exec.dynamic.partition.mode", "nonstrict").getOrCreate()
val gsm = new GetSourceMeta()
val minMaxKeyMap = gsm.getBounds(keyIdMap).onComplete {
case Success(values) => values.foreach(println)
case Failure(f) => f.printStackTrace
}
.
.
.
}
好吧,onComplete
没有打印任何值,所以我按如下方式使用andThen
,这也没有帮助。
val bounds: Future[scala.collection.mutable.Map[String, String]] = gpMetaData.getBounds(incrementalIds) andThen {
case Success(outval) => outval.foreach(println)
case Failure(e) => println(e)
}
主线程更早退出而没有让Future:getBounds执行。因此,我无法在终端上显示任何来自Future的println语句。我发现我需要保持主线程等待才能完成Future。但是当我在main和onComplete一起使用Await时:
Await.result(bounds, Duration.Inf)
编译器给出错误:
Type mismatch, expected: Awaitable[NotInferedT], actual:Unit
如果我将val minMaxKeyMap声明为Future[scala.collection.mutable.Map[String, String]
,则编译器会说:Expression of type Unit doesn't conform to expected type Future[mutable.map[String,String]]
我试图在Await语句后打印bounds
的值,但这只是打印一个空的Map。
我不知道该如何解决。谁能让我知道我该怎么做才能使Future正常运行?
答案 0 :(得分:0)
在这种情况下,始终最好遵循这些类型。方法 onComplete 仅返回Unit,它不会返回Future,因此无法使用Await传递。
例如,如果要返回任何类型的Future,则必须将值映射或平面映射并返回一个选项。在这种情况下,无论返回什么,都只希望Await方法等待此结果并打印跟踪。您可以在恢复中处理可能的异常。就像在您的代码中一样:
val minMaxKeyMap:Future[Option[Any] = gsm.getBounds(keyIdMap).map { values =>
values.foreach(println)
None
}.recover{
case e: Throwable =>
e. printStackTrace
None
}
请注意,recover部分必须返回该类型的实例。 之后,您可以将“等待”应用于“将来”,然后将结果打印出来。这不是最漂亮的解决方案,但可以解决您的问题。