Composing a nested model with specklepy

I’m composing a deeply nested manufacturing model using specklepy. It’s slow and I’m wondering how I can make my service more efficient.

I have a python service that receives a tree whose nodes are either parts or assemblies. Assemblies are just collections of parts and/or assemblies. My service traverses the input tree and creates a tree of speckle objects (nothing custom, just Collections and BlockInstances). The traversal is memoized so that assemblies and parts are only created once.

At each node, it sends the BlockDefinition of the part or assembly to my stream and commits it to its own branch i.e. part/<part_name> or assembly/<assembly_name>. When the traversal is complete, it also commits the full speckle tree to the main branch.

As the traversal approaches the root node, the objects are very large and sometimes the main commit fails because there are too many objects. Is there any way to reference the objects created in the previous commits so that my main commit isn’t a massive tree of BlockInstances/BlockDefinitions and Collections that all need to be sent to speckle again? Or maybe this is already happening under the hood?

As an aside, what does detaching actually do on the backend? I’ve been assuming it just creates a new entry in the objects table so that object has its own data value instead of being nested in another object’s data.

Detaching does nothing specific on the backend it is a pointer to the frontend (middleend?) or at least the sending/receiving “client”. It is the Transport and the Serializer that handles the mechanics of this for you before sending. And the deserializer that stitches your data back together again on receive.

You probably found the docs on detaching: Decomposition API | Speckle Docs but if not, re-read.

An Instance object is a Base object with a defintion and a transform: Objects.Other.Instance
A definition is a Base object.

The geometry of a definition is annotated as detached.

You can also synthesise a model version commit with [ObjectReference](https://github.com/specklesystems/speckle-sharp/blob/e28f84e62b3582a135fbd292207ebdc6a9f4088e/Core/Core/Models/Extras.cs#L62) objects; not part of the Objects schema but a means of ‘recycling’ object definitions in a version commit manually. It’s not strictly Instance/Definition but more generic - and if you are always programmatically defining objects, it might be appropriate.

All of this is somewhat abstract without looking at the actual code. I can understand functionally what you are trying to do, but it’s unclear what might be failing. “Too many objects” doesn’t seem like an error you should experience.

You may, however, be experiencing something we are working to resolve around _closures, but I can’t tell from this distance.

Thanks JB

Can I create a reference to a commit’s referenceId and then use it as the definition for an Instance?

Something like this…?

class ObjectReference(Base):
    speckle_type: str = "reference"
    referencedId: str

    def __init__(self, referenced_id: str, **kwargs):
        super().__init__(**kwargs)
        self.referencedId = referenced_id

reference = ObjectReference(commitReferencedId)

instance = BlockInstance(...)

instance['@definition'] = reference

Seems legit.

I wrote about some of this in a federating models mini tutorial

The gotcha regarding _closures at the end is worth noting. We are reviewing the use of _closures, but for now, this is a requirement of the Speckle viewer.

1 Like

So what you’re saying is that you’ve already made a step by step, incredibly detailed guide on how to do exactly what I’m trying to do while also capturing some helpful lessons on how Speckle works. Thank you @jonathon!

I’m going to do some reflecting on how to get better at searching your docs, but in the meantime, this is solving my challenge.

This is more my fault than yours