INTEGRITY Документация

Начало работы

Это руководство проведёт вас через следующие шаги:

Чтобы узнать больше о Durable Objects, см. Что такое Durable Objects?.

быстрый старт

Если вы хотите пропустить шаги и быстро начать работу, нажмите кнопку ниже.

Deploy to Cloudflare

Это создаёт репозиторий в вашем аккаунте GitHub и разворачивает приложение в Cloudflare Workers. Выберите этот вариант, если вы уже знакомы с Cloudflare Workers и хотите пропустить пошаговые инструкции.

Если вы только начинаете работать с Cloudflare Workers, можете пройти все шаги вручную.

Предварительные требования

  1. Зарегистрируйтесь для получения Аккаунт Cloudflare ↗.
  2. Установка Node.js ↗.

менеджер версий Node.js

Используйте менеджер версий Node, например Volta ↗ или nvm ↗ чтобы избежать проблем с правами доступа и переключать версии Node.js. Wrangler, о котором пойдёт речь далее в этом руководстве, требует версию Node 16.17.0 или более поздней версии.

1. Создайте проект Worker

Вы будете обращаться к своему Durable Object из Worker. Приложение Worker служит интерфейсом для взаимодействия с вашим Durable Object.

Чтобы создать проект Worker, выполните:

npm create cloudflare@latest -- durable-object-starter

Выполнение create cloudflare@latest установит Wrangler, интерфейс командной строки Workers. Вы будете использовать Wrangler для тестирования и развёртывания своего проекта.

Для настройки выберите следующие параметры:

Это создаст новый каталог, в котором будет либо src/index.js или src/index.ts файл для написания кода и wrangler.jsonc файл конфигурации.

Перейдите в новый каталог:

cd durable-object-starter

2. Напишите класс Durable Object с использованием SQL API

Прежде чем создавать Durable Object и обращаться к нему, его поведение нужно определить обычным экспортируемым классом JavaScript.

Ваш MyDurableObject класс будет иметь конструктор с двумя параметрами. Первый параметр, ctx, передаваемый в конструктор класса, содержит состояние, специфичное для Durable Object, включая методы доступа к хранилищу. Второй параметр, env, содержит все bindings, которые вы связали с Worker при его загрузке.

export class MyDurableObject extends DurableObject {
	constructor(ctx, env) {
		// Required, as we're extending the base class.
		super(ctx, env);
	}
}
export class MyDurableObject extends DurableObject<Env> {
	constructor(ctx: DurableObjectState, env: Env) {
		// Required, as we're extending the base class.
		super(ctx, env)
	}
}
from workers import DurableObject

class MyDurableObject(DurableObject):
    def __init__(self, ctx, env):
        super().__init__(ctx, env)

Workers взаимодействуют с Durable Object с помощью удалённый вызов процедур. Публичные методы класса Durable Object доступны как Методы RPC чтобы его можно было вызвать из другого Worker.

Теперь ваш файл должен выглядеть так:

export class MyDurableObject extends DurableObject {
	constructor(ctx, env) {
		// Required, as we're extending the base class.
		super(ctx, env);
	}

	async sayHello() {
		let result = this.ctx.storage.sql
			.exec("SELECT 'Hello, World!' as greeting")
			.one();
		return result.greeting;
	}
}
export class MyDurableObject extends DurableObject<Env> {
	constructor(ctx: DurableObjectState, env: Env) {
		// Required, as we're extending the base class.
		super(ctx, env)
	}

    async sayHello(): Promise<string> {
    	let result = this.ctx.storage.sql
    		.exec("SELECT 'Hello, World!' as greeting")
    		.one();
    	return result.greeting;
    }

}
from workers import DurableObject

class MyDurableObject(DurableObject):
    async def say_hello(self):
        result = self.ctx.storage.sql.exec(
            "SELECT 'Hello, World!' as greeting"
        ).one()

        return result.greeting

В приведённом выше коде вы:

  1. Определён RPC-метод, sayHello(), который может быть вызван Worker для взаимодействия с Durable Object.
  2. Реализован доступ к подключённому хранилищу Durable Object, приватной базе данных SQLite, доступной только самому объекту, с помощью SQL API методы (sql.exec()) доступно на ctx.storage .
  3. Возвращает объект, представляющий результат запроса в виде одной строки, с помощью one(), который проверяет, что результат запроса содержит ровно одну строку.
  4. Возврат greeting столбец из объекта результата строки.

3. Создание экземпляра Durable Object и обмен данными с ним

Worker используется для Доступ к Durable Objects.

Чтобы взаимодействовать с Durable Object, обработчик fetch в Worker должен выглядеть примерно так:

export default {
	async fetch(request, env, ctx) {
		const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);

		const greeting = await stub.sayHello();

		return new Response(greeting);
	},
};
export default {
	async fetch(request, env, ctx): Promise<Response> {
    	const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);

    	const greeting = await stub.sayHello();

    	return new Response(greeting);
    },

} satisfies ExportedHandler<Env>;
from workers import handler, Response, WorkerEntrypoint
from urllib.parse import urlparse

class Default(WorkerEntrypoint):
    async def fetch(request):
        url = urlparse(request.url)
        stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
        greeting = await stub.say_hello()
        return Response(greeting)

В приведённом выше коде вы:

  1. Экспортировали основные обработчики событий вашего Worker, такие как fetch()-обработчик для получения HTTP-запросов.
  2. Передано env в fetch()-обработчик. Привязки (bindings) передаются как свойство объекта окружения, который передаётся вторым параметром при вызове обработчика события или конструктора класса.
  3. Создана заглушка (stub) для экземпляра Durable Object на основе переданного имени. Заглушка представляет собой клиентский объект, который используется для отправки сообщений Durable Object.
  4. Обратился к Durable Object, вызвав RPC метод, sayHello(), на Durable Object, который возвращает Hello, World! строку приветствия.
  5. Возврат HTTP-ответа клиенту путём создания HTTP Response с return new Response().

См. Доступ к Durable Object из Worker чтобы узнать больше о взаимодействии с Durable Object.

4. Настройка привязок Durable Object

Bindings позволяют вашим Workers взаимодействовать с ресурсами платформы Cloudflare для разработчиков. Привязки Durable Object в конфигурационном файле вашего проекта Worker конфигурационный файл Wrangler будет включать имя привязки (в этом руководстве используется MY_DURABLE_OBJECT) и имя класса (MyDurableObject).

{
	"durable_objects": {
		"bindings": [
			{
				"name": "MY_DURABLE_OBJECT",
				"class_name": "MyDurableObject"
			}
		]
	}
}
[[durable_objects.bindings]]
name = "MY_DURABLE_OBJECT"
class_name = "MyDurableObject"

bindings раздел содержит следующие поля:

5. Настройка класса Durable Object с бэкендом хранения SQLite

Каждый класс Durable Object, экспортируемый вашим Worker, объявляется в exports поле файла конфигурации Wrangler. Cloudflare использует это объявление, чтобы выделить пространство имён для класса при первом развёртывании и управлять его жизненным циклом при последующих развёртываниях (переименование, удаление, перенос).

Минимальный exports блок для регистрации нового класса Durable Object с хранилищем SQLite выглядит так:

{
	"exports": {
		"MyDurableObject": {
			"type": "durable-object",
			"storage": "sqlite"
		}
	}
}
[exports.MyDurableObject]
type = "durable-object"
storage = "sqlite"

См. Экспорт классов Durable Object чтобы узнать больше об объявлении и управлении классами Durable Object. Если у вас уже есть Worker на устаревшем migrations массив, см. Миграции классов Durable Object (устаревший способ).

6. Локальная разработка Durable Object Worker

Чтобы протестировать свой Durable Object локально, выполните wrangler dev:

npx wrangler dev

В консоли вы должны увидетьHello world строку, возвращённую Durable Object.

7. Развёртывание Durable Object Worker

Чтобы развернуть Worker с Durable Object:

npx wrangler deploy

После развёртывания вы сможете увидеть только что созданный Durable Object Worker на панели управления Cloudflare.

Перейдите в Workers & Pages ↗

Предварительный просмотр Worker с Durable Object доступен по адресу <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev.

Итоги и финальный код

Итоговый код должен выглядеть так:

import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject {
	constructor(ctx, env) {
		// Required, as we are extending the base class.
		super(ctx, env);
	}

	async sayHello() {
		let result = this.ctx.storage.sql
			.exec("SELECT 'Hello, World!' as greeting")
			.one();
		return result.greeting;
	}
}
export default {
	async fetch(request, env, ctx) {
		const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);

		const greeting = await stub.sayHello();

		return new Response(greeting);
	},
};
index.ts
import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject<Env> {
	constructor(ctx: DurableObjectState, env: Env) {
		// Required, as we are extending the base class.
		super(ctx, env)
	}

    async sayHello():Promise<string> {
    	let result = this.ctx.storage.sql
    		.exec("SELECT 'Hello, World!' as greeting")
    		.one();
    	return result.greeting;
    }

}
export default {
async fetch(request, env, ctx): Promise<Response> {
const stub = env.MY_DURABLE_OBJECT.getByName(new URL(request.url).pathname);

    	const greeting = await stub.sayHello();

    	return new Response(greeting);
    },

} satisfies ExportedHandler<Env>;
from workers import DurableObject, handler, Response
from urllib.parse import urlparse

class MyDurableObject(DurableObject):
    async def say_hello(self):
        result = self.ctx.storage.sql.exec(
            "SELECT 'Hello, World!' as greeting"
        ).one()

        return result.greeting

class Default(WorkerEntrypoint):
    async def fetch(self, request):
        url = urlparse(request.url)
        stub = self.env.MY_DURABLE_OBJECT.getByName(url.path)
        greeting = await stub.say_hello()
        return Response(greeting)

После завершения этого руководства вы: