შეყვანილი Kaigi JavaScript აპლიკაციაში
Kaigi საშუალებას აძლევს აპლიკაციას შექმნას კაპიტალის მხარდაჭერილი ერთი-ერთ აუდიო/ვიდეო შეხვედრები, რომელთა სიცოცხლის ციკლი დაფიქსირებულია Iroha საშუალებით. ბრაუზერი კვლავ მართავს მედიას WebRTC, ხოლო Torii და Kaigi ინსტრუქციები უზრუნველყოფენ მდგრადი შეხვედრების ჩანაწერს, კოდირებულ სიგნალიზაციის მეტა მონაცემებს, კერძო სიაში მხარდაჭერას და გამოყენების მოვლენებს.
ეს სახელმძღვანელო აჩვენებს მინიმალურ ინტეგრაციის ნიმუშს, რომელსაც იყენებს Iroha დემო JavaScript აპლიკაცია:
- რედაქტორი ქმნის შეთავაზებებს და პასუხებს WebRTC
- აპლიკაცია ხიდზე აწერს და Kaigi ტრანზაქციებს წარადგენს
- კომპაქტური მოწვევის ბმულები შეიცავს მხოლოდ ზარს ID და მოწვევა საიდუმლო
- მასპინძელი უყურებს Torii ჩიფრული მონაწილეების პასუხებზე
მაგალითები იყენებენ TypeScript და იწერება ისე, რომ მათ შეუძლიათ გაუშვათ Electron- ში, ბრაუზერში უსაფრთხო უკანა მხარით ან ვებ აპლიკაციაზე ქაღალდის გაფართოებით. ინახეთ პირადი გასაღებები არასაიმედო რენდერის კოდის გარეთ წარმოებისას.
წინაპირობები
თქვენ გჭირდებათ:
- Kaigi-სუნებრიობის Torii საბოლოო წერტილი
- ანგარიში მასპინძლისა და სტუმარისათვის.
- წვდომა თითოეული ანგარიშის ხელმოწერის გასაღები უსაფრთხო აპლიკაციის ხიდის ან საფულის მეშვეობით.
- ბრაუზერის კამერა/მიკროფონის ნებართვები
- Node.js 20+ თუ თქვენ იყენებთ JavaScript დემოს ან მშობლიურ
@iroha/iroha-jsდამაკავშირებელ პირდაპირს
სრული სამუშაო რეფერენციის მისაღებად, კლონირებული დემო Iroha წყარო გადახდის გვერდით:
mkdir iroha-wallet-workspace
cd iroha-wallet-workspace
git clone https://github.com/hyperledger-iroha/iroha.git
git clone https://github.com/soramitsu/iroha-demo-javascript.git
cd iroha/javascript/iroha_js
npm install
npm run build:native
npm run build:dist
cd ../../../iroha-demo-javascript
npm install
npm run devგამოიყენეთ დემო @iroha/iroha-js ძმური Iroha წყარო რეპოზიტორიდან. მისი file: დამოკიდებულება უშუალოდ ხსნის გადახდას. თუ ადგილობრივი კავშირი იცვლება, აღადგინეთ იგი iroha/javascript/iroha_js; სუფთა პაკეტის დირექტორი არ შეიცავს სატვირთო სამუშაო სივრცეს, რომელიც საჭიროა npm run build:native.
სანამ TAIRA-ზე პირდაპირი შეხვედრა ჩატარდება, შეამოწმეთ საჯარო Torii ზედაპირი, რომელზეც დემო დამოკიდებულია:
TAIRA=https://taira.sora.org
curl -fsS "$TAIRA/health"
curl -fsS "$TAIRA/v1/kaigi/relays"
curl -fsS "$TAIRA/v1/kaigi/relays/health"ეს ბრძანებები ადასტურებს, რომ TAIRA არის ცოცხალი და რომ Kaigi რელე ტელემეტრიია ხელმისაწვდომია. ისინი არ წარუდგენენ Kaigi ტრანზაქციებს. რეალური CreateKaigi ან JoinKaigi ტესტი საჭიროა ფინანსირებული TAIRA ანგარიშები და ხელმოწერა დემოს ხიდზე ან სხვა ქაღალდის მხარდაჭერით ხიდზე.
არქიტექტურა
ინტეგრაციის Kaigi გაყოფა სამ ფენაზე:
| ფენა | პასუხისმგებლობა |
|---|---|
| UI | ანგარიშის შერჩევა, შეხვედრის ფორმა, მოწვევის ბმულის ჩვენება, მედიის კონტროლი |
| WebRTC | RTCPeerConnection, ადგილობრივი მედია, შეთავაზების და პასუხის აღწერილობა |
| Iroha ხიდი | ხელმოწერა, CreateKaigi, JoinKaigi, EndKaigi, სიგნალების გამოკითხვა |
აპლიკაციის ხიდი შეიძლება იყოს ელექტრონული წინასწარ დატვირთვა API, ქაღალდის გაფართოება ან ფულის ბოლო წერტილი. ეს უნდა გამოავლინოს მცირე ზედაპირი UI:
type KaigiMeetingPrivacy = "private" | "transparent";
type KaigiPeerIdentityReveal = "Hidden" | "RevealAfterJoin";
type KaigiSignalKeyPair = {
publicKeyBase64Url: string;
privateKeyBase64Url: string;
};
type KaigiDescription = {
type: "offer" | "answer";
sdp: string;
};
type KaigiMeeting = {
callId: string;
meetingCode: string;
title?: string;
hostAccountId?: string;
hostDisplayName?: string;
hostParticipantId?: string;
hostKaigiPublicKeyBase64Url: string;
scheduledStartMs: number;
expiresAtMs: number;
live: boolean;
ended: boolean;
privacyMode: KaigiMeetingPrivacy;
peerIdentityReveal: KaigiPeerIdentityReveal;
rosterRootHex: string;
offerDescription: { type: "offer"; sdp: string };
};
type KaigiSignal = {
entrypointHash: string;
callId: string;
participantId: string;
participantName: string;
createdAtMs: number;
answerDescription: { type: "answer"; sdp: string };
};
type KaigiBridge = {
generateKaigiSignalKeyPair(): KaigiSignalKeyPair;
createKaigiMeeting(input: {
toriiUrl: string;
chainId: string;
hostAccountId: string;
callId: string;
title?: string;
scheduledStartMs: number;
meetingCode: string;
inviteSecretBase64Url: string;
hostDisplayName: string;
hostParticipantId: string;
hostKaigiPublicKeyBase64Url: string;
offerDescription: { type: "offer"; sdp: string };
privacyMode: KaigiMeetingPrivacy;
peerIdentityReveal: KaigiPeerIdentityReveal;
}): Promise<{ hash: string }>;
getKaigiCall(input: {
toriiUrl: string;
callId: string;
inviteSecretBase64Url: string;
}): Promise<KaigiMeeting>;
joinKaigiMeeting(input: {
toriiUrl: string;
chainId: string;
participantAccountId: string;
callId: string;
hostAccountId?: string;
hostKaigiPublicKeyBase64Url: string;
participantId: string;
participantName: string;
walletIdentity?: string;
roomId: string;
privacyMode: KaigiMeetingPrivacy;
rosterRootHex: string;
answerDescription: { type: "answer"; sdp: string };
}): Promise<{ hash: string }>;
pollKaigiMeetingSignals(input: {
toriiUrl: string;
accountId: string;
callId: string;
hostKaigiKeys: KaigiSignalKeyPair;
afterTimestampMs?: number;
}): Promise<KaigiSignal[]>;
watchKaigiCallEvents(
input: { toriiUrl: string; callId: string },
onEvent: (event: { kind: string; callId: string }) => void | Promise<void>,
): Promise<string>;
endKaigiMeeting(input: {
toriiUrl: string;
chainId: string;
hostAccountId: string;
callId: string;
endedAtMs?: number;
}): Promise<{ hash: string }>;
};დემო აპლიკაციაში, ეს ხიდის მეთოდები განხორციელებულია @iroha/iroha-js, ადგილობრივი ხელმოწერა, დაშიფვრა Kaigi მეტა მონაცემებით და Torii ზარით.
დაპატიჟეთ დამხმარეები
გამოიყენეთ Torii-თან თავსებადი ზარი IDs ფორმაში domain.dataspace:meeting. დემო იყენებს kaigi.universal:<call-name> გენერირებული შეხვედრებისთვის.
const KAIGI_WINDOW_MS = 24 * 60 * 60 * 1000;
const base64Url = (bytes: Uint8Array): string =>
btoa(String.fromCharCode(...bytes))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/g, "");
export function createInviteSecret(): string {
const bytes = new Uint8Array(24);
crypto.getRandomValues(bytes);
return base64Url(bytes);
}
export function createMeetingCode(): string {
const bytes = new Uint8Array(8);
crypto.getRandomValues(bytes);
return base64Url(bytes).toLowerCase();
}
export function buildKaigiCallId(domain: string, meetingCode: string): string {
const qualifiedDomain = domain.includes(".") ? domain : `${domain}.universal`;
const safeCode = meetingCode
.toLowerCase()
.replace(/[^a-z0-9-]+/g, "-")
.replace(/^-|-$/g, "");
return `${qualifiedDomain}:kaigi-${safeCode || "meeting"}`;
}
export function buildInviteLink(input: {
callId: string;
inviteSecretBase64Url: string;
}): string {
const call = encodeURIComponent(input.callId);
const secret = encodeURIComponent(input.inviteSecretBase64Url);
return `iroha://kaigi/join?call=${call}&secret=${secret}`;
}
export function parseInviteLink(link: string): {
callId: string;
inviteSecretBase64Url: string;
} {
const url = new URL(link);
const callId = url.searchParams.get("call")?.trim();
const inviteSecretBase64Url = url.searchParams.get("secret")?.trim();
if (!callId || !inviteSecretBase64Url) {
throw new Error("Kaigi invite link is missing call or secret.");
}
return { callId, inviteSecretBase64Url };
}WebRTC დამხმარეები
მასპინძელი ქმნის შეთავაზებას, ინახავს მას CreateKaigi, და ფანჯარა გახსნილია ისე, რომ მას შეუძლია გამოიყენოს სტუმრის პასუხი. სტუმარი იძიებს კოდირებულ შეთავაზებებს, ქმნის პასუხს და აქვეყნებს პასუხს JoinKaigi .
const rtcConfig: RTCConfiguration = {
iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
};
export async function openLocalMedia(): Promise<MediaStream> {
return navigator.mediaDevices.getUserMedia({
audio: true,
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 24, max: 30 },
},
});
}
export function createPeer(localStream: MediaStream): RTCPeerConnection {
const peer = new RTCPeerConnection(rtcConfig);
for (const track of localStream.getTracks()) {
peer.addTrack(track, localStream);
}
return peer;
}
async function waitForIceGathering(peer: RTCPeerConnection): Promise<void> {
if (peer.iceGatheringState === "complete") {
return;
}
await new Promise<void>((resolve) => {
const done = () => {
if (peer.iceGatheringState === "complete") {
peer.removeEventListener("icegatheringstatechange", done);
resolve();
}
};
peer.addEventListener("icegatheringstatechange", done);
});
}
export async function createOfferDescription(
peer: RTCPeerConnection,
): Promise<{ type: "offer"; sdp: string }> {
const offer = await peer.createOffer();
await peer.setLocalDescription(offer);
await waitForIceGathering(peer);
const local = peer.localDescription;
if (!local?.sdp || local.type !== "offer") {
throw new Error("WebRTC offer was not created.");
}
return { type: "offer", sdp: local.sdp };
}
export async function createAnswerDescription(
peer: RTCPeerConnection,
offer: { type: "offer"; sdp: string },
): Promise<{ type: "answer"; sdp: string }> {
await peer.setRemoteDescription(offer);
const answer = await peer.createAnswer();
await peer.setLocalDescription(answer);
await waitForIceGathering(peer);
const local = peer.localDescription;
if (!local?.sdp || local.type !== "answer") {
throw new Error("WebRTC answer was not created.");
}
return { type: "answer", sdp: local.sdp };
}მიაერთეთ ნაკადები თქვენს UI ჩვეულებრივი ვიდეო ელემენტებით:
export function attachKaigiMedia(input: {
peer: RTCPeerConnection;
localStream: MediaStream;
localVideo: HTMLVideoElement;
remoteVideo: HTMLVideoElement;
}): void {
input.localVideo.srcObject = input.localStream;
const remoteStream = new MediaStream();
input.remoteVideo.srcObject = remoteStream;
input.peer.addEventListener("track", (event) => {
if (event.streams[0]) {
input.remoteVideo.srcObject = event.streams[0];
return;
}
remoteStream.addTrack(event.track);
});
}მასპინძელი: შექმენით შეხვედრის ბმული
მასპინძელი ნაკადი:
- ღია კამერა და მიკროფონი
- შეიქმნას Kaigi სიგნალის გასაღები წყვილი
- შეიქმნას შეთავაზება WebRTC
- წარადგინოს
CreateKaigi - გაუზიარეთ კომპაქტური მოწვევის ბმული
type AccountContext = {
accountId: string;
displayName: string;
};
type KaigiContext = {
bridge: KaigiBridge;
toriiUrl: string;
chainId: string;
};
export async function hostKaigiMeeting(input: {
context: KaigiContext;
account: AccountContext;
title?: string;
privacyMode?: KaigiMeetingPrivacy;
}): Promise<{
callId: string;
inviteLink: string;
peer: RTCPeerConnection;
localStream: MediaStream;
hostKaigiKeys: KaigiSignalKeyPair;
createdAtMs: number;
}> {
const { bridge, toriiUrl, chainId } = input.context;
const privacyMode = input.privacyMode ?? "private";
const scheduledStartMs = Date.now();
const meetingCode = createMeetingCode();
const callId = buildKaigiCallId("kaigi", meetingCode);
const inviteSecretBase64Url = createInviteSecret();
const hostKaigiKeys = bridge.generateKaigiSignalKeyPair();
const localStream = await openLocalMedia();
const peer = createPeer(localStream);
const offerDescription = await createOfferDescription(peer);
await bridge.createKaigiMeeting({
toriiUrl,
chainId,
hostAccountId: input.account.accountId,
callId,
title: input.title,
scheduledStartMs,
meetingCode,
inviteSecretBase64Url,
hostDisplayName: input.account.displayName,
hostParticipantId: "host",
hostKaigiPublicKeyBase64Url: hostKaigiKeys.publicKeyBase64Url,
offerDescription,
privacyMode,
peerIdentityReveal: "Hidden",
});
return {
callId,
inviteLink: buildInviteLink({ callId, inviteSecretBase64Url }),
peer,
localStream,
hostKaigiKeys,
createdAtMs: scheduledStartMs,
};
}აჩვენეთ inviteLink თქვენი UI. მომხმარებელს შეუძლია აკოპიროს იგი, გახსნას სხვა საფულეში ან გადაიყვანოს ის აპლიკაციის მარშრუტით, როგორიცაა:
export function inviteRoute(inviteLink: string): string {
const invite = parseInviteLink(inviteLink);
return `/kaigi?call=${encodeURIComponent(invite.callId)}&secret=${encodeURIComponent(
invite.inviteSecretBase64Url,
)}`;
}სტუმარი: მიდი შეხვედრაზე
სტუმრების ნაკადი:
- შეამოწმეთ მოწვევა
- მოიტანეთ დაშიფვრილი ზარის შეთავაზება Torii
- შეიქმნას WebRTC პასუხი
- წარადგინოს
JoinKaigiდაშიფვრილი პასუხის მეტა მონაცემებით
export async function joinKaigiMeetingFromInvite(input: {
context: KaigiContext;
account: AccountContext;
inviteLink: string;
}): Promise<{
callId: string;
peer: RTCPeerConnection;
localStream: MediaStream;
}> {
const { bridge, toriiUrl, chainId } = input.context;
const { callId, inviteSecretBase64Url } = parseInviteLink(input.inviteLink);
const meeting = await bridge.getKaigiCall({
toriiUrl,
callId,
inviteSecretBase64Url,
});
if (meeting.ended) {
throw new Error("This Kaigi meeting has already ended.");
}
if (Date.now() > meeting.expiresAtMs) {
throw new Error("This Kaigi invite has expired.");
}
const localStream = await openLocalMedia();
const peer = createPeer(localStream);
const answerDescription = await createAnswerDescription(
peer,
meeting.offerDescription,
);
await bridge.joinKaigiMeeting({
toriiUrl,
chainId,
participantAccountId: input.account.accountId,
callId: meeting.callId,
hostAccountId: meeting.hostAccountId,
hostKaigiPublicKeyBase64Url: meeting.hostKaigiPublicKeyBase64Url,
participantId: "guest",
participantName: input.account.displayName,
roomId: meeting.callId,
privacyMode: meeting.privacyMode,
rosterRootHex: meeting.rosterRootHex,
answerDescription,
});
return { callId: meeting.callId, peer, localStream };
}თუ შეხვედრა გამჭვირვალეა, შეგიძლიათ შეავსოთ ქაღალდის ჩვენების სიგელი გაერთიანების თხოვნაში. კერძო შეხვედრებისთვის, შეინახეთ walletIdentity, თუ მომხმარებელი მკაფიოდ არ ირჩევს გამოავლინოს ეს.
მასპინძელი: გამოიყენე სტუმრის პასუხი
ცოცხალი შეხვედრის შექმნის შემდეგ, მასპინძელმა უნდა უყუროს Kaigi მოვლენებს და გამოკითხოს კოდირებული პასუხის სიგნალების შესახებ. გამოიყენეთ პირველი ბერული პასუხი მასპინძლის თანატოლთა კავშირზე.
export async function watchForKaigiAnswer(input: {
context: KaigiContext;
hostAccountId: string;
callId: string;
hostKaigiKeys: KaigiSignalKeyPair;
createdAtMs: number;
peer: RTCPeerConnection;
onParticipant?: (signal: KaigiSignal) => void;
}): Promise<string | null> {
const { bridge, toriiUrl } = input.context;
const seenSignals = new Set<string>();
let lastSignalAtMs = input.createdAtMs;
const checkSignals = async (): Promise<boolean> => {
const signals = await bridge.pollKaigiMeetingSignals({
toriiUrl,
accountId: input.hostAccountId,
callId: input.callId,
hostKaigiKeys: input.hostKaigiKeys,
afterTimestampMs: lastSignalAtMs,
});
const next = signals.find(
(signal) => !seenSignals.has(signal.entrypointHash),
);
if (!next) {
return false;
}
seenSignals.add(next.entrypointHash);
lastSignalAtMs = Math.max(lastSignalAtMs, next.createdAtMs);
await input.peer.setRemoteDescription(next.answerDescription);
input.onParticipant?.(next);
return true;
};
if (await checkSignals()) {
return null;
}
return bridge.watchKaigiCallEvents(
{ toriiUrl, callId: input.callId },
async (event) => {
if (event.kind !== "ended") {
await checkSignals();
}
},
);
}შეინახეთ დაბრუნებული აბონენტი ID ისე, რომ თქვენი UI შეიძლება შეაჩეროს დამკვირვებელი, როდესაც მასპინძელი დახურავს ან ნავიგირებს გარეთ.
შეხვედრის დასრულება
შეწყვიტეთ ზარი იმავე მასპინძელი ანგარიშიდან, რომელმაც შექმნა ის:
export async function endKaigi(input: {
context: KaigiContext;
hostAccountId: string;
callId: string;
peer?: RTCPeerConnection;
localStream?: MediaStream;
}): Promise<void> {
input.peer?.close();
input.localStream?.getTracks().forEach((track) => track.stop());
await input.context.bridge.endKaigiMeeting({
toriiUrl: input.context.toriiUrl,
chainId: input.context.chainId,
hostAccountId: input.hostAccountId,
callId: input.callId,
endedAtMs: Date.now(),
});
}კერძო რეჟიმის დაფინანსება
კერძო Kaigi შექმნა, გაერთიანება და დასრულების ოპერაციები შეიძლება მოითხოვოს დაცული XOR კერძო შესასვლელი პუნქტის საფასურისათვის. თქვენი აპლიკაცია უნდა აღმოაჩინოს ეს შეცდომა და სთავაზობს თვითშეზღუდვის ქმედება, სანამ განმეორებით ცდილობს.
type PrivateKaigiFundingBridge = KaigiBridge & {
getPrivateKaigiConfidentialXorState(input: {
toriiUrl: string;
accountId: string;
}): Promise<{
shieldedBalance: string | null;
transparentBalance: string;
canSelfShield: boolean;
message?: string;
}>;
selfShieldPrivateKaigiXor(input: {
toriiUrl: string;
chainId: string;
accountId: string;
amount: string;
}): Promise<{ hash: string }>;
};
export async function selfShieldForPrivateKaigi(input: {
context: Omit<KaigiContext, "bridge"> & {
bridge: PrivateKaigiFundingBridge;
};
accountId: string;
amount: string;
}): Promise<void> {
const { bridge, toriiUrl, chainId } = input.context;
const state = await bridge.getPrivateKaigiConfidentialXorState({
toriiUrl,
accountId: input.accountId,
});
if (!state.canSelfShield) {
throw new Error(
state.message || "This account cannot self-shield XOR for private Kaigi.",
);
}
await bridge.selfShieldPrivateKaigiXor({
toriiUrl,
chainId,
accountId: input.accountId,
amount: input.amount,
});
}დემოში, UI მოუწოდებს მომხმარებელს თვითშეზღუდვას და შემდეგ განახორციელოს ორიგინალური შექმნის ან შეუერთების ქმედება.
საბაგირო ჩავარდნა
ავტომატური სიგნალი დამოკიდებულია ცოცხალ საფულეზე, Kaigi -შეწყობილი Torii მარშრუტებზე და მტკიცებულების გამომუშავებაზე კერძო რეჟიმში. შეინახეთ ხელით განვითარებისა და შეზღუდული გარემოსთვის:
- თუ
CreateKaigiწარუმატებელია, აჩვენეთ შეთავაზების შემცველი სახელმძღვანელო მოწვევა. - თუ
JoinKaigiარ გამოვა, აჩვენეთ ნედლეული პასუხის პაკეტი. - დაუშვას მასპინძელს დააჭიროს პასუხის პაკეტი და დარეკოს
setRemoteDescription
სასწრაფო რეჟიმში ჩართვისას WebRTC-ის დებეგირება სასარგებლოა, მაგრამ იგი არ უზრუნველყოფს იმავე კერძო ქსელზე სიგნალიზაციის გარანტიებს, როგორც ცოცხალი Kaigi ნაკადი.
ტესტის შეამოწმებელი სია
გაზომილების გამოცდებისთვის, აჩვენეთ ხიდი და ადასტურეთ, რომ თქვენი UI გადადის მოსალოდნელი Kaigi სასარგებლო ტვირთები:
- მასპინძელი ქმნის ადგილობრივ მედიასაშუალებებს და წარადგენს
createKaigiMeeting - მასპინძელი აჩვენებს
iroha://kaigi/join?call=...&secret=...მოწვევას. - სტუმარი შეისწავლის მოწვევას, ეძახება
getKaigiCallდა წარადგენსjoinKaigiMeeting; - მასპინძელი გამოკითხვები ან საათები პასუხის სიგნალებისათვის და იყენებს პასუხს
- კერძო რეჟიმში თვითგადაფარვის ინსტრუმენტები, როდესაც დაცული XOR არ არსებობს
- ხელმოწერილი ჩავარდნა გამოჩნდება, როდესაც ცოცხალი სიგნალი არ არის ხელმისაწვდომი.
სრული რეფერენციული ტესტის კომპლექტისათვის იხილეთ დემოს აპლიკაციის Kaigi ნახვა და პრეტენზიული ხიდის ტესტები:
npm test -- tests/kaigiView.spec.ts tests/preloadKaigiBridge.spec.ts
npm run e2e:uiUI სიგარეტის ტესტი ადასტურებს, რომ /kaigi მარშრუტი გამოსცემს. რეალურ მედია-ტესტს ჯერ კიდევ სჭირდება ორი დაფინანსებული საფულე და ორი ფანჯარა ან მოწყობილობა, რადგან ტრანზაქციის ხელმოწერის, კამერის, მიკროფონის და WebRTC ნებართვების შეღავათი იცვლება შესრულების დროით.
თუ თქვენ ტესტირებთ TAIRA-ის წინააღმდეგ და ზარის სპეციფიკური მარშრუტი ბრუნდება 404, პირველ რიგში დაადასტურეთ, რომ მასპინძელი საფულე წარმატებით წარედგინა CreateKaigi. რელეი ჯანმრთელობის საბოლოო წერტილები შეიძლება ხელმისაწვდომი იყოს ნებისმიერი კონკრეტული ზარის არსებობამდე.
შემდეგი ნაბიჯები
- დაამატეთ გამოყენების ჩანაწერი
RecordKaigiUsageმაშინ, როდესაც თქვენს აპლიკაციას აქვს საიმედო სესიის ხანგრძლივობის გათვლა. - რეგისტრაცია და კონტროლი რელიეების
/v1/kaigi/relaysსაშუალებით, როდესაც გამოიყენება რელიე მანიფესტები. - ზედაპირის
KaigiRosterSummary,KaigiUsageSummaryდაKaigiRelayHealthUpdatedმოვლენები თქვენი ოპერატორის დაშბორდის.