Internal Dcc Model Spc Version
This page describes how to maintain the native model, and highlights some potential pitfalls with the the cache.
SPC Version
All requests that are sent to the native core will be encoded as binary. The encoding is done with a specific SPC version. The range of supported versions are hardcoded in DccModel.Internal.SpcVersion
The native core might support a greater range of versions, but the Api and the backend will reject requests with unsupported versions, regardless of whether they understand the message or not.
When updating the native core, we can decide to update the supported versions as well. More info on that in the section "Maintaining SPC Version" below.
The following is how it is supposed to work when we reach production. At the time of writing this might not actually be the case though
Updating SPC Version
When an update is pushed to production, the backends will start to redeploy. Only once all backends have redeployed, the api-servers will redeploy.
This should ensure that a backend will never receive a message with an unsupported spc-version. There is a short window while the api-servers are redeploying where one api might report a higher supported spc-version to a client, which will then attept to use that version with an api-server that hasn't redeployed yet.
For now we accept this, and will assume the clients can just retry their request.
Maintaining SPC Version
All data that is sent to the native core is serialized with the
DccModel.Internal.Serialization.DccSerializer
class
The classes are either annotated with
DccModel.Internal.Serialization.DccSerializableAttribute
, or implements
DccModel.Internal.Serialization.IDccSerializable
.
For DccModel.Internal.Serialization.IDccSerializable please refer to documentation in code
The classes annotated with
DccModel.Internal.Serialization.DccSerializableAttribute
are expected to
mirror the native classes. By annotating the members with DccDataAttribute
serializers that can handle different spc message versions will be
autogenerated.
For example. Given the following c++ class in the dcc, where a change is introduced in version 81, we would get:
class DccExample
{
int m_IntegerMember;
string m_StringMemberFromV81;
public:
void SPCCircumstances::Read(DCC::MessageIStream& mis)
{
int version = DCC::SPCMessageVersion::Instance()->GetCurrentVersion();
mis >> m_IntegerMember;
if (version >= 81)
mis >> m_StringMemberFromV81;
}
void SPCCircumstances::Write(DCC::MessageOStream& mos) const
{
int version = DCC::SPCMessageVersion::Instance()->GetCurrentVersion();
mos << m_IntegerMember;
if (version >= 81)
mos << m_StringMemberFromV81;
}
};
Mapped to c# we'd get
[DccSerializable]
class DccExample
{
[DccData]
public int IntegerMember {get;set;}
[DccData(MinVersion = 81)]
public string StringMemberFromV81 {get;set;}
}
If you update the supported range of SPC versions, make sure all data modelled in the global dcc is updated if it is affected by the newly available versions.
Known Problems
- Even if we redeploy all backends before any api-servers, there will be a window where the api-servers support different versions. This could mean that a client requests the highest supported version, and then starts using a version that isn't supported by all running api-servers which could lead to failures
- If we are running multiple client spc-versions there might be cases where distances cached for the older clients can't be used by the newer clients