Skip to content

Commit a6e0c42

Browse files
[main] Update 2025-12-30.22 (#419)
Reference commit: e7c5d269dc
1 parent c1c6b99 commit a6e0c42

File tree

604 files changed

+30748
-5924
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

604 files changed

+30748
-5924
lines changed

UNRELEASED.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ For parties with signing keys both in `PartyToParticipant` and `PartyToKeyMappin
4242
an optional argument, as well as `filter-party`.
4343
- Protect the admin participant from self lock-out. It is now impossible for an admin to remove own admin rights or
4444
delete itself.
45+
- *BREAKING* The default OTLP gRPC port that the Canton connects to in order to export the traces has been changed from
46+
4318 to 4317. This aligns the default configuration of Canton with the default configuration of the OpenTelemetry
47+
Collector. This change affects only the users who have configured an OTLP trace export through
48+
```
49+
canton.monitoring.tracing.tracer.exporter.type=otlp
50+
```
4551

4652
### Preview Features
4753
- preview feature
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.daml.concurrent
5+
6+
import scala.concurrent as sc
7+
8+
sealed abstract class ExecutionContextOf {
9+
type T[+P] <: sc.ExecutionContext
10+
private[concurrent] def subst[F[_], P](fe: F[sc.ExecutionContext]): F[T[P]]
11+
}
12+
13+
object ExecutionContextOf {
14+
val Instance: ExecutionContextOf = new ExecutionContextOf {
15+
type T[+P] = sc.ExecutionContext
16+
override private[concurrent] def subst[F[_], P](fe: F[sc.ExecutionContext]) = fe
17+
}
18+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.daml.concurrent
5+
6+
import scalaz.std.scalaFuture.*
7+
import scalaz.{Catchable, Cobind, Isomorphism, Leibniz, MonadError, Nondeterminism, Semigroup}
8+
9+
import scala.concurrent as sc
10+
import scala.language.implicitConversions
11+
import scala.util.Try
12+
13+
import Isomorphism.<~>
14+
import Leibniz.===
15+
16+
sealed abstract class FutureOf {
17+
18+
/** We don't use [[scala.concurrent.Future]] as the upper bound because it has methods that
19+
* collide with the versions we want to use, i.e. those that preserve the phantom `EC` type
20+
* parameter. By contrast, [[scala.concurrent.Awaitable]] has only the `ready` and `result`
21+
* methods, which are mostly useless.
22+
*/
23+
type T[-EC, +A] <: sc.Awaitable[A]
24+
private[concurrent] def subst[F[_[+_]], EC](ff: F[sc.Future]): F[T[EC, +*]]
25+
}
26+
27+
/** Instances and methods for `FutureOf`. You should not import these; instead, enable
28+
* `-Xsource:2.13` and they will always be available without import.
29+
*/
30+
object FutureOf {
31+
val Instance: FutureOf = new FutureOf {
32+
type T[-EC, +A] = sc.Future[A]
33+
override private[concurrent] def subst[F[_[+_]], EC](ff: F[sc.Future]) = ff
34+
}
35+
36+
type ScalazF[F[+_]] = Nondeterminism[F]
37+
with Cobind[F]
38+
with MonadError[F, Throwable]
39+
with Catchable[F]
40+
41+
implicit def `future Instance`[EC: ExecutionContext]: ScalazF[Future[EC, +*]] =
42+
Instance.subst[ScalazF, EC](implicitly)
43+
44+
implicit def `future Semigroup`[A: Semigroup, EC: ExecutionContext]: Semigroup[Future[EC, A]] = {
45+
type K[T[+_]] = Semigroup[T[A]]
46+
Instance.subst[K, EC](implicitly)
47+
}
48+
49+
implicit def `future is any type`[A]: sc.Future[A] === Future[Any, A] =
50+
Instance.subst[Lambda[`t[+_]` => sc.Future[A] === t[A]], Any](Leibniz.refl)
51+
52+
/** A [[scala.concurrent.Future]] converts to our [[Future]] with any choice of EC type. */
53+
implicit def `future is any`[A](sf: sc.Future[A]): Future[Any, A] =
54+
`future is any type`(sf)
55+
56+
private[this] def unsubstF[Arr[_, +_], A, B](f: A Arr Future[Nothing, B]): A Arr sc.Future[B] = {
57+
type K[T[+_]] = (A Arr T[B]) => A Arr sc.Future[B]
58+
(Instance.subst[K, Nothing](identity))(f)
59+
}
60+
61+
def swapExecutionContext[L, R]: Future[L, *] <~> Future[R, *] =
62+
Instance.subst[Lambda[`t[+_]` => t <~> Future[R, *]], L](
63+
Instance.subst[Lambda[`t[+_]` => sc.Future <~> t], R](implicitly[sc.Future <~> sc.Future])
64+
)
65+
66+
/** Common methods like `map` and `flatMap` are not provided directly; instead, import the
67+
* appropriate Scalaz syntax for these; `scalaz.syntax.bind._` will give you `map`, `flatMap`,
68+
* and most other common choices. Only exotic Future-specific combinators are provided here.
69+
*/
70+
implicit final class Ops[-EC, +A](private val self: Future[EC, A]) extends AnyVal {
71+
72+
/** `.require[NEC]` is a friendly alias for `: Future[NEC, A]`. */
73+
def require[NEC <: EC]: Future[NEC, A] = self
74+
75+
def transform[B](f: Try[A] => Try[B])(implicit ec: ExecutionContext[EC]): Future[EC, B] =
76+
self.removeExecutionContext transform f
77+
78+
// The rule of thumb is "EC determines what happens next". So `recoverWith`
79+
// doesn't let the Future returned by pf control what EC it uses to *call* pf,
80+
// because that happens "before". Same with `transformWith`. By contrast,
81+
// zipWith's f gets called "after" the two futures feeding it arguments, so
82+
// we allow both futures control over the EC used to invoke f.
83+
84+
def transformWith[LEC <: EC, B](f: Try[A] => Future[LEC, B])(implicit
85+
ec: ExecutionContext[EC]
86+
): Future[LEC, B] =
87+
self.removeExecutionContext transformWith unsubstF(f)
88+
89+
def collect[B](pf: A PartialFunction B)(implicit ec: ExecutionContext[EC]): Future[EC, B] =
90+
self.removeExecutionContext collect pf
91+
92+
def failed: Future[EC, Throwable] = self.removeExecutionContext.failed
93+
94+
def fallbackTo[LEC <: EC, B >: A](that: Future[LEC, B]): Future[LEC, B] =
95+
self.removeExecutionContext fallbackTo that.removeExecutionContext
96+
97+
def filter(p: A => Boolean)(implicit ec: ExecutionContext[EC]): Future[EC, A] =
98+
self.removeExecutionContext filter p
99+
100+
def withFilter(p: A => Boolean)(implicit ec: ExecutionContext[EC]): Future[EC, A] =
101+
self.removeExecutionContext withFilter p
102+
103+
def recover[B >: A](pf: Throwable PartialFunction B)(implicit
104+
ec: ExecutionContext[EC]
105+
): Future[EC, B] =
106+
self.removeExecutionContext recover pf
107+
108+
def recoverWith[LEC <: EC, B >: A](pf: Throwable PartialFunction Future[LEC, B])(implicit
109+
ec: ExecutionContext[EC]
110+
): Future[EC, B] =
111+
self.removeExecutionContext recoverWith unsubstF(pf)
112+
113+
def transform[B](s: A => B, f: Throwable => Throwable)(implicit
114+
ec: ExecutionContext[EC]
115+
): Future[EC, B] =
116+
self.removeExecutionContext.transform(s, f)
117+
118+
def foreach[U](f: A => U)(implicit ec: ExecutionContext[EC]): Unit =
119+
self.removeExecutionContext foreach f
120+
121+
def andThen[U](pf: Try[A] PartialFunction U)(implicit ec: ExecutionContext[EC]): Future[EC, A] =
122+
self.removeExecutionContext andThen pf
123+
124+
def onComplete[U](f: Try[A] => U)(implicit ec: ExecutionContext[EC]): Unit =
125+
self.removeExecutionContext onComplete f
126+
127+
def zip[LEC <: EC, B](that: Future[LEC, B]): Future[LEC, (A, B)] = {
128+
type K[T[+_]] = (T[A], T[B]) => T[(A, B)]
129+
Instance.subst[K, LEC](_ zip _)(self, that)
130+
}
131+
132+
def zipWith[LEC <: EC, B, C](
133+
that: Future[LEC, B]
134+
)(f: (A, B) => C)(implicit ec: ExecutionContext[LEC]): Future[LEC, C] = {
135+
type K[T[+_]] = (T[A], T[B]) => T[C]
136+
Instance.subst[K, LEC](_.zipWith(_)(f))(self, that)
137+
}
138+
}
139+
140+
/** Operations that don't refer to an ExecutionContext. */
141+
implicit final class NonEcOps[+A](private val self: Future[Nothing, A]) extends AnyVal {
142+
143+
/** Switch execution contexts for later operations. This is not necessary if `NEC <: EC`, as the
144+
* future will simply widen in those cases, or you can use `require` instead, which implies
145+
* more safety.
146+
*/
147+
def changeExecutionContext[NEC]: Future[NEC, A] =
148+
swapExecutionContext[Nothing, NEC].to(self)
149+
150+
/** The "unsafe" conversion to Future. Does nothing itself, but removes the control on which
151+
* [[scala.concurrent.ExecutionContext]] is used for later operations.
152+
*/
153+
def removeExecutionContext: sc.Future[A] =
154+
self.changeExecutionContext[Any].asScala
155+
156+
def isCompleted: Boolean = self.removeExecutionContext.isCompleted
157+
158+
def value: Option[Try[A]] = self.removeExecutionContext.value
159+
}
160+
161+
/** Operations safe if the Future is set to any ExecutionContext. */
162+
implicit final class AnyOps[+A](private val self: Future[Any, A]) extends AnyVal {
163+
164+
/** The "safe" conversion to Future. `EC = Any` already means "use any ExecutionContext", so
165+
* there is little harm in restating that by referring directly to [[scala.concurrent.Future]].
166+
*/
167+
def asScala: sc.Future[A] = `future is any type`[A].flip(self)
168+
}
169+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) 2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.daml
5+
6+
import scalaz.Id.Id
7+
8+
import scala.concurrent as sc
9+
import scala.util.Try
10+
11+
/** A compatible layer for `scala.concurrent` with extra type parameters to control
12+
* `ExecutionContext`s. Deliberately uses the same names as the equivalent concepts in
13+
* `scala.concurrent`.
14+
*
15+
* The trouble with [[scala.concurrent.ExecutionContext]] is that it is used incoherently. This
16+
* leads to the problems described in
17+
* https://failex.blogspot.com/2020/05/global-typeclass-coherence-principles-3.html . The extension
18+
* layer in this package adds a phantom type parameter to `ExecutionContext` and related types, so
19+
* that types can be used to discriminate between ExecutionContexts at compile-time, and so Futures
20+
* can declare which ExecutionContext their operations are in.
21+
*
22+
* For Scala 2.12, you must pass `-Xsource:2.13` to scalac for methods and conversions to be
23+
* automatically found. You must also `import scalaz.syntax.bind._` or similar for Future methods
24+
* like `map`, `flatMap`, and so on.
25+
*
26+
* There are no constraints on the `EC` type variable; you need only declare types you wish to use
27+
* for it that are sufficient for describing the domains in which you want ExecutionContexts to be
28+
* discriminated. These types will never be instantiated, so you can simply declare that they
29+
* exist. They can be totally separate, or have subtyping relationships; any subtyping
30+
* relationships they have will be reflected in equivalent subtyping relationships between the
31+
* resulting `ExecutionContext`s; if you declare `sealed trait Elephant extends Animal`, then
32+
* automatically `ExecutionContext[Elephant] <: ExecutionContext[Animal]` with scalac preferring
33+
* the former when available (because it is "more specific"). They can even be singleton types, so
34+
* you might use `x.type` to suggest that the context is associated with the exact value of the `x`
35+
* variable.
36+
*
37+
* If you want to, say, refer to both [[scala.concurrent.Future]] and [[concurrent.Future]] in the
38+
* same file, we recommend importing *the containing package* with an alias rather than renaming
39+
* each individual class you import. For example,
40+
*
41+
* {{{
42+
* import com.daml.concurrent._
43+
* import scala.{concurrent => sc}
44+
* // OR
45+
* import scala.concurrent._
46+
* import com.daml.{concurrent => dc}
47+
* }}}
48+
*
49+
* The exact name isn't important, but you should pick a short one that is sufficiently suggestive
50+
* for you.
51+
*
52+
* You should always be able to remove the substring `Of.Instance.T` from any inferred type; we
53+
* strongly suggest doing this for clarity.
54+
*
55+
* Demonstrations of the typing behavior can be found in FutureSpec and ExecutionContextSpec. This
56+
* library has no interesting runtime characteristics; you should think of it as exactly like
57+
* `scala.concurrent` in that regard.
58+
*/
59+
package object concurrent {
60+
61+
/** Like [[scala.concurrent.Future]] but with an extra type parameter indicating which
62+
* [[ExecutionContext]] should be used for `map`, `flatMap` and other operations.
63+
*/
64+
type Future[-EC, +A] = FutureOf.Instance.T[EC, A]
65+
66+
/** A subtype of [[scala.concurrent.ExecutionContext]], more specific as `P` gets more specific.
67+
*/
68+
type ExecutionContext[+P] = ExecutionContextOf.Instance.T[P]
69+
}
70+
71+
// keeping the companions with the same-named type aliases in same file
72+
package concurrent {
73+
74+
import java.util.concurrent.ExecutorService
75+
76+
object Future {
77+
78+
/** {{{
79+
* Future[MyECTag] { expr }
80+
* }}}
81+
*
82+
* returns `Future[MyECTag, E]` where `E` is `expr`'s inferred type and
83+
* `ExecutionContext[MyECTag]` is required implicitly.
84+
*/
85+
def apply[EC]: apply[EC] =
86+
new apply(())
87+
88+
@scala.annotation.nowarn("msg=dubious usage of method hashCode with unit value")
89+
final class apply[EC](private val ignore: Unit) extends AnyVal {
90+
def apply[A](body: => A)(implicit ec: ExecutionContext[EC]): Future[EC, A] =
91+
sc.Future(body)(ec)
92+
}
93+
94+
def fromTry[EC, A](result: Try[A]): Future[EC, A] =
95+
sc.Future.fromTry(result)
96+
}
97+
98+
object ExecutionContext {
99+
100+
/** Explicitly tag an [[scala.concurrent.ExecutionContext]], or replace the tag on an
101+
* [[ExecutionContext]].
102+
*/
103+
def apply[EC](ec: sc.ExecutionContext): ExecutionContext[EC] =
104+
ExecutionContextOf.Instance.subst[Id, EC](ec)
105+
106+
def fromExecutorService[EC](e: ExecutorService): ExecutionContext[EC] =
107+
apply(sc.ExecutionContext.fromExecutorService(e))
108+
109+
val parasitic: ExecutionContext[Nothing] =
110+
ExecutionContext(sc.ExecutionContext.parasitic)
111+
}
112+
}

0 commit comments

Comments
 (0)