-
Notifications
You must be signed in to change notification settings - Fork 199
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
JSON API: etx-500 add type information into the package ids of template ids #19211
JSON API: etx-500 add type information into the package ids of template ids #19211
Conversation
33507f8
to
2b8802f
Compare
2b8802f
to
e17517c
Compare
e17517c
to
7cb03aa
Compare
sdk/fmt.sh
Outdated
@@ -51,7 +51,7 @@ check_diff() { | |||
# "${@:3}" command | |||
changed_files=$(git diff --name-only --diff-filter=ACMRT "$1" | grep $2 | grep -E -v '^canton(-3x)?/' || [[ $? == 1 ]]) | |||
if [[ -n "$changed_files" ]]; then | |||
run "${@:3}" ${changed_files[@]:-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a developer, we now run ./fmt.sh --diff
from within the sdk/
dir, but git still returns a list of changed files with a sdk
prefix. This change removes the sdk/
prefix from those paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this change but in a small test I did the prefix removal only applied to the first file, so:
- As this is an inf change it may be better to put it in a dedicated PR (@garyverhaegen-da may have an opinion on this)
- As the canton pattern match in change files seems to assume no no sdk prefix so will not work
- Consider
changed_files=$(git diff --name-only --diff-filter=ACMRT "$1" | grep $2 | sed 's/^sdk\///' | grep -E -v '^canton(-3x)?/' || [[ $? == 1 ]])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted here #19237
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this change but in a small test I did the prefix removal only applied to the first file, so:
- As this is an inf change it may be better to put it in a dedicated PR (@garyverhaegen-da may have an opinion on this)
I really don't - I don't use the pre-commit. My only opinion on the whole thing is it should be opt-in rather than opt-out.
log: LogHandler, | ||
lc: LoggingContextOf[InstanceUUID], | ||
): ConnectionIO[SurrogateTpId] = surrogateTemplateId(None, packageId, moduleName, entityName) | ||
|
||
final def surrogateTemplateId( | ||
packageName: Option[String], | ||
packageId: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Within the db cache, we always use a package id as the basis for the surrogate template ids, i.e. an integeter which corresponds to a specific template.
parties: domain.PartySet, | ||
contractTypeIds: List[ContractTypeId.Resolved], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used to build a template filter for grpc requests to the ledger. In these filters the package may be specified with a name or an id, and this function is agnostic to the package type.
@@ -89,22 +89,22 @@ package domain { | |||
) | |||
|
|||
object ActiveContract { | |||
type ResolvedCtTyId[+LfV] = ActiveContract[ContractTypeId.Resolved, LfV] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ActiveContract
is always something that is returned from the ledger, and as such it the template ids are specified with a specific package id.
|
||
def apply(id: ContractTypeId.Resolved): ExtractAs[ContractTypeId.Resolved] = id match { | ||
def apply(id: ContractTypeId.Definite[_]): ExtractAs[ContractTypeId.Definite] = id match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can build an ExtractAs
without considering the form of package of the id we queried, which is why the type parameter for it is _
.
|
||
private[this] def qualifiedName(a: CtId[_]): Ref.QualifiedName = | ||
Ref.QualifiedName( | ||
Ref.DottedName.assertFromString(a.moduleName), | ||
Ref.DottedName.assertFromString(a.entityName), | ||
) | ||
|
||
final def toLedgerApiValue(a: RequiredPkg): Ref.Identifier = { | ||
final def toLedgerApiValue(a: RequiredPkgId): Ref.Identifier = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice we only use this for calculating a contract key hash. If the type is from a package new enough to have a package name, then the package id portion is ignored and replaced with the name for the purposes of calculating the hash. If it's older, then the package id would be the appropriate package specifier anyway.
sealed abstract class ContractTypeRef[+CtTyId]( | ||
orig: CtTyId, | ||
ids: NonEmpty[Seq[CtTyId]], | ||
sealed abstract class ContractTypeRef[+CtTyId[T] <: ContractTypeId[T]]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now the original
field will always use a package reference, but latestPkgId
and allPkgIds
will always use package ids. This was the case before, but not encoded by the types as they all used used strings.
To support this, ContractTypeRef
, also moves from being parameterised with a type, to being parameterised with a type constructor. This is so that we can have different package specifiers for different fields, which both share the same contract type, e.g. original
returns Template[PackageRef]
but latestPkgId
returns Template[PackageId]
.
@@ -71,7 +71,7 @@ private class ContractsFetch( | |||
jwt: Jwt, | |||
ledgerId: LedgerApiDomain.LedgerId, | |||
parties: domain.PartySet, | |||
templateIds: List[domain.ContractTypeId.Resolved], | |||
templateIds: List[domain.ContractTypeId.ResolvedPkgId], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything within this module relates to the db cache and thus needs to work with package ids.
@@ -478,44 +474,48 @@ object PackageService { | |||
|
|||
def buildTemplateIdMap[CtId[T] <: ContractTypeId.Definite[T] with ContractTypeId.Ops[CtId, T]]( | |||
idName: PackageNameMap, | |||
ids: Set[RequiredPkg[CtId]], | |||
ids: Set[CtId[Ref.PackageId]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These contract ids come out of hte package definition itself, and thus will have the package id embedded within them.
genDuplicateModuleEntityApiIdentifiers.map(xs => | ||
xs.map(domain.ContractTypeId.Template.fromLedgerApi) | ||
) | ||
|
||
final case class PackageIdGen[A](gen: Gen[A]) | ||
|
||
implicit val RequiredPackageIdGen: PackageIdGen[String] = PackageIdGen(Gen.identifier) | ||
private val genPkgIdentifier = Gen.identifier.map(s => s.substring(0, 64 min s.length)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Package ids may not be longer than 64 chars, so just truncate the randomised values to that length.
e8d8c63
to
7020195
Compare
…nd in the case that we queried an interface we can still just get the template id out of the ArchivedEvent, rather than having to use the one we queried with
…ore consistent type alias names. We may want to coverhaul these names though as they are still not very clear run-all-tests: true
7020195
to
51f45f0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good apart from the fmt.sh
change that would be better moved into a different PR.
sdk/fmt.sh
Outdated
@@ -51,7 +51,7 @@ check_diff() { | |||
# "${@:3}" command | |||
changed_files=$(git diff --name-only --diff-filter=ACMRT "$1" | grep $2 | grep -E -v '^canton(-3x)?/' || [[ $? == 1 ]]) | |||
if [[ -n "$changed_files" ]]; then | |||
run "${@:3}" ${changed_files[@]:-} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this change but in a small test I did the prefix removal only applied to the first file, so:
- As this is an inf change it may be better to put it in a dedicated PR (@garyverhaegen-da may have an opinion on this)
- As the canton pattern match in change files seems to assume no no sdk prefix so will not work
- Consider
changed_files=$(git diff --name-only --diff-filter=ACMRT "$1" | grep $2 | sed 's/^sdk\///' | grep -E -v '^canton(-3x)?/' || [[ $? == 1 ]])
|
||
final def fromLedgerApi(in: lav1.value.Identifier): RequiredPkg = | ||
apply(in.packageId, in.moduleName, in.entityName) | ||
final def fromLedgerApi(in: lav1.value.Identifier): RequiredPkgId = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean when reading from the DB or reading from the ledger-API ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
A template/interface id (
ContractTypeId
) consists of three parts: package, module and entity.So far the package portion has been modeled with a
String
, where that string could represent either a package name or a package id, depending on whether it started with a"#"
prefix or not, respectively. However there are parts of the code, namely those that deal with the db cache, that are designed to work with contract type ids whose package portion is only a package id. The type system was not helping us to ensure this so far.Fortunately the
ContractTypeId
class is parameterised with the type of the package, so this PR replaces all existing instantiations which usedString
packages, with either PackageId or PackageRef (which is a sum type which can contain either aPackageId
or aPackageName
).The
ContractTypeRef
type contains all the package info we have about a contract type id. Itsoriginal
field now returns aContractTypeId[PackageRef]
, whereas itslatestPkgId
returns aContractTypeId[PackageId]
. This helps us to ensure that we are passing around the right kind of package specifiers to the parts of the code that need one or the other.There are some type aliases used, that may be useful to help read and understand the changes, which tend to look like
i.e. if it ends with Pkg it uses a
PackgeRef
and if it ends with PkgId uses aPackageId
.Note also that the
Resolved
terminology is an orthogonal concern which refers to whether this id has been determined to belong to a template vs interface (i.e. it extendsDefinite
), or whether that is not yet known.