Shared Protobuf event schemas for toGather microservices
Project description
togather-shared-events
This repository contains event schemas for the toGather event-driven backend system. We use Protocol Buffers (Protobuf) as the messaging format for events. It provides type-safe code generation for TypeScript and Python, enabling services in different languages to share a consistent event schema.
Table of Contents
Directory Structure
Protobuf files should follow a domain/version-based structure:
proto/
└── <domain>/
└── <version>/
└── <event>.proto
- Domain: The feature or module (e.g.,
user) - Version: The event schema version (e.g.,
v1)
Example:
proto/user/v1/UserCreated.proto
This structure ensures forward-compatibility and makes schema evolution manageable.
SDK Development
Adding New Proto Files
- Place your
.protofile in the appropriateproto/<domain>/<version>folder. - Define the
packagein the.protofile to match the folder structure.
Example for user.create.v1:
syntax = "proto3";
package user.create.v1;
message UserCreated {
string id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
}
Linting
Lint your proto files to ensure consistency and adherence to standards:
pnpm buf:lint
This checks for things like missing packages, incorrect directory structure, and other style issues.
Code Generation
Generate TypeScript and Python code from your proto files:
pnpm buf:generate
The generated code is placed in the gen/ directory:
gen/ts/...
gen/python/...
Tip: Keep
buf.gen.yamlupdated if you add new languages or plugins.
Publishing Package
To publish the package, run the following command:
pnpm run release
This command performs the following steps:
- Deletes the old build artifacts.
- Lints the proto files.
- Generates new code for TypeScript and Python.
- Patches the npm version.
- Publishes the package to the registry.
Note: Ensure all changes are committed and tested before running this command.
Using Generated Code
TypeScript
Dependencies:
pnpm add @bufbuild/protobuf@^2.9.0
Example usage:
import {UserCreated,UserCreatedSchema} from '@togatherlabs/event-sdk/user/v1'
import { create, toBinary, fromBinary, toJson } from '@bufbuild/protobuf';
// Create a new message
const newUser: UserCreated = create(UserCreatedSchema, {
id: "1",
name: "Abhiram",
email: "abhiram.ars@gmail.com",
createdAt: BigInt(Date.now()),
});
// Serialize to binary
const buffer = toBinary(UserCreatedSchema, newUser);
// Deserialize from binary
const decoded = fromBinary(UserCreatedSchema, buffer);
// Convert to JSON
const json = toJson(UserCreatedSchema, decoded);
Tip: Use
toBinary/fromBinaryfor Kafka or network transmission. UsetoJson/fromJsonfor logging or debugging.
Python
Install dependencies (for usage):
pip install protobuf togather-event-sdk
Dependencies (for maintainers / publishing):
pip install build twine
Example usage:
from togather_event_sdk.user.v1 import UserCreated
# Create a new message
msg = UserCreated(
id="1",
name="Abhiram",
email="abhiram@gmail.com",
created_at=int(1728512345123),
)
# Serialize to bytes
binary_data = msg.SerializeToString()
# Deserialize from bytes
decoded = UserCreated()
decoded.ParseFromString(binary_data)
print(decoded)
Build & Publish Python SDK (for maintainers):
pnpm python:build
This runs:
- buf generate
- Adds init.py files
- Builds the Python wheel + source tarball
Tip: Python type hints can be added with
mypy-protobufor community plugins for full static type checking.
Best Practices
-
Package and folder alignment
packagein.protomust match folder structure (proto/<domain>/<version>).
-
Versioning
- Always increment the version folder (
v1,v2, etc.) when changing message formats to avoid breaking consumers.
- Always increment the version folder (
-
Type safety
- Use the generated schemas rather than manually constructing messages.
- In TypeScript, always use
create(); in Python, use the generatedUserCreatedclass.
-
Schema evolution
- Avoid renaming or deleting existing fields; mark them deprecated instead.
- Use
int64for timestamps,stringfor IDs/emails, etc.
How to Type a Event
A Event will have many fields like
message DomainEventExample {
/// event name (e.g. "user.account.created")
string event_name = 1;
/// Schema version (e.g."v1"), reciving systems can use this to deserialize the payload accordingly with version
string event_version = 2;
/// The entity or aggregate this event belongs to (for partitioning)
string aggregate_id = 3;
/// Binary-encoded event data (the inner protobuf message),will be typed check events for specific event
bytes payload = 4;
/// Epoch timestamp in milliseconds when the event was created,indicate when this action was recorded by the system
int64 timestamp = 5;
}
How should you type a event
syntax = "proto3";
package admin.v1;
import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
string fixed_value = 50001;
}
message Payload {
string id = 10; // Account ID
string email = 11; // Account email
string name = 12; // Account name
int64 created_at = 13; // Account creation timestamp
}
message AdminAccountCreated {
// Common metadata fields (in every event)
// "admin.account.created"
string event_name = 1 [(fixed_value) = "admin.account.created"];
string event_version = 2; // "v1"
string aggregate_id = 3; // Account ID for partitioning
int64 timestamp = 4; // When event was created
string trace_id = 5; // For distributed tracing
Payload payload = 9; // Event-specific data
}
check the docs to see why this decistion was taken: docs
Troubleshooting
-
ModuleNotFoundError in Python
- Ensure
gen/folder is in yourPYTHONPATH. - Add
__init__.pyfiles in each subfolder if needed.
- Ensure
-
TypeScript errors with missing
$typeNameorUserCreated- Make sure you are importing the schema (
UserCreatedSchema) and usingcreate()instead of instantiating the type directly.
- Make sure you are importing the schema (
-
Buf generation issues
- Run
pnpm buf:lintfirst to catch package/directory mismatches.
- Run
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file togather_event_sdk-1.0.61.tar.gz.
File metadata
- Download URL: togather_event_sdk-1.0.61.tar.gz
- Upload date:
- Size: 30.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df61731e24d4ecc204d4d6b25272ebdb80ea1f433dd3cade1b22109a39601415
|
|
| MD5 |
b4e59c9a09c15f204376a4058418c62d
|
|
| BLAKE2b-256 |
f0f167897efd708758a772cdfc5601186cb230f50d30a34497412dbabe269179
|
File details
Details for the file togather_event_sdk-1.0.61-py3-none-any.whl.
File metadata
- Download URL: togather_event_sdk-1.0.61-py3-none-any.whl
- Upload date:
- Size: 47.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f6c7a9d50268c4b275da91f1297f2e1bffc985bcc3f5354a0bc721b1b64c7bd
|
|
| MD5 |
80241e301a95baaf3c06cea9ea66888c
|
|
| BLAKE2b-256 |
4113b43993aca37cbe0d900f15bcb10f9942ce6ccd12a093b4ba12bf9ed3cf9c
|