Skip to content

Core Concepts

Simon Lambin edited this page Nov 21, 2021 · 5 revisions

The Silex client repository implements some concepts that are bound to the Silex pipeline. The other repositories like silex_maya, silex_houdini... Are like plug-ins that uses these concepts

Context

The Context object is a singleton-like object that keeps track of the context's data (shot, task, user, project...). You can get the context with the static method Silex.get(). Silex gets all its data from the zou API, using the environment variable SILEX_ZOU_HOST. The context is defined by the environment variable SILEX_TASK_ID which is the id of the task entity in the zou database. The Context class will populate its metadata lazily from this ID. If you want to change context, you can set a different SILEX_TASK_ID, and set Context.is_outdated to true. The metadata will be recomputed when needed.

You can also set the task id in the cli:

silex action <action-name> --task-id <task-id>
silex launch --dcc <dcc-name> --task-id <task-id>

The context is used multiple times across silex, every actions you execute will be dependent of the context you were in when creating the action. The action creates its own copy when it is created, to prevent errors. If the context is changed while some commands are executing, it will not affect the running actions since they will work on their copy made when they where created.

Actions

Whenever a user wants to do something on the pipeline, it will be through an action. An action is a serie of commands that are executed in order can communicate together through their parameters as input and returned value as output. The ActionQuery object is the entry point for every action, it is responsible to execute, stop, rewind the action, set parameters, communicate the progression or prompt to the silex front end... All the data of the action is stored in buffer objects. The ActionBuffer contains StepBuffers which contains CommandBuffers which contains ParameterBuffers. These classes are dataclasses, they store the action's state and are responsible to serialize and deserialize the action's data (convert to json and interpret from json)

When an action is created, it is resolved according to the context it is created from. The context is then baked in the action, if the user changes the context the action will still work like if it was in the context it was created from. The idea is to have multiple definition of the same action across silex_maya, silex_houdini... and silex_client pick the right one thanks to the SILEX_ACTION_CONFIG environment variable and the silex_action entry point. Since actions can inherit from each other, you can create base actions that will be reused in the different implementations of each actions. As an example, for one action publish, silex_client would have to chose according to a graph like this:

action_graph

An action is represented by an ActionQuery object. This object is meant to keep track of the progression of the action and to communicate with the web UI to prompt the user for some parameters, keep him informed of the progression and the potential errors. Everything that is related to the action is stored in this ActionQuery object, this object will be responsible to transfer all the infos about the action and all the updates. The ActionQuery object will make comings and goings between the execution of the action in the DCC and the UI. The parcours of an ActionQuery object could be represented like this:

action_pingpong

Commands

Commands compose the actions. A command definition is a piece of standalone code that can be called from an action. You can think of them like a function.

Event loop

Everything silex_client executes is executed in a secondary thread to avoid freezing the DCCs while executing. This thread is running an asyncio event loop that runs the tasks responsible to:

  • Communicate with the UI through websocket
  • Execute the commands of the actions.

The EventLoop class is here to allow you to send tasks to the event loop. Some methods are present twice, one prefixed with async_ and one without. It means that the version with async_ is meant to be called from within the loop (from other tasks) and the one without, from the main thread. The reason is that the version without the async_ prefix will make sure to send the task to the event loop in a thread safe manner.

📚 Doc

🔧 Introduction:

🚀 Development:

Clone this wiki locally