Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Migration/Destinations/Appwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public static function getSupportedResources(): array
* @throws AppwriteException
*/
#[Override]
public function report(array $resources = []): array
public function report(array $resources = [], array $resourceIds = []): array
{
if (empty($resources)) {
$resources = $this->getSupportedResources();
Expand Down
2 changes: 1 addition & 1 deletion src/Migration/Destinations/CSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static function getSupportedResources(): array
];
}

public function report(array $resources = []): array
public function report(array $resources = [], array $resourceIds = []): array
{
return [];
}
Expand Down
2 changes: 1 addition & 1 deletion src/Migration/Destinations/Local.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static function getSupportedResources(): array
/**
* @throws \Exception
*/
public function report(array $resources = []): array
public function report(array $resources = [], array $resourceIds = []): array
{
$report = [];

Expand Down
146 changes: 94 additions & 52 deletions src/Migration/Sources/Appwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,7 @@ class Appwrite extends Source
public const SOURCE_API = 'api';
public const SOURCE_DATABASE = 'database';

// Debug logging for specific projects
public static array $debugProjects = [
'67ec0369002bd8a96885' => 'SimpMusic#Maxrave',
'6838382d0014e002589c' => 'Fastwrite#DocuTrust',
];
private const DEFAULT_PAGE_LIMIT = 25;

protected Client $client;

Expand Down Expand Up @@ -163,23 +159,26 @@ public function getDatabasesBatchSize(): int

/**
* @param array<string> $resources
* @param array<string, array<string>> $resourceIds
* @return array<string, mixed>
*
* @throws \Exception
*/
public function report(array $resources = []): array
public function report(array $resources = [], array $resourceIds = []): array
{
$this->validateResourceIds($resourceIds);

$report = [];

if (empty($resources)) {
$resources = $this->getSupportedResources();
}

try {
$this->reportAuth($resources, $report);
$this->reportDatabases($resources, $report);
$this->reportStorage($resources, $report);
$this->reportFunctions($resources, $report);
$this->reportAuth($resources, $report, $resourceIds);
$this->reportDatabases($resources, $report, $resourceIds);
$this->reportStorage($resources, $report, $resourceIds);
$this->reportFunctions($resources, $report, $resourceIds);

$report['version'] = $this->call(
'GET',
Expand All @@ -205,23 +204,27 @@ public function report(array $resources = []): array
/**
* @param array $resources
* @param array $report
* @param array<string, array<string>> $resourceIds
* @throws AppwriteException
*/
private function reportAuth(array $resources, array &$report): void
private function reportAuth(array $resources, array &$report, array $resourceIds = []): void
{
// check if we need to fetch teams!
$needTeams = !empty(array_intersect(
[Resource::TYPE_TEAM, Resource::TYPE_MEMBERSHIP],
$resources
));

$pageLimit = 25;
$teams = ['total' => 0, 'teams' => []];

if (\in_array(Resource::TYPE_USER, $resources)) {
$report[Resource::TYPE_USER] = $this->users->list(
[Query::limit(1)]
)['total'];
$userQueries = $this->buildQueries(
resourceType: Resource::TYPE_USER,
resourceIds: $resourceIds,
limit: 1
);
$userList = $this->users->list($userQueries);
$report[Resource::TYPE_USER] = $userList['total'];
}

if ($needTeams) {
Expand All @@ -230,12 +233,11 @@ private function reportAuth(array $resources, array &$report): void
$lastTeam = null;

while (true) {
$params = $lastTeam
// TODO: should we use offset here?
// this, realistically, shouldn't be too much ig
? [Query::cursorAfter($lastTeam)]
: [Query::limit($pageLimit)];

$params = $this->buildQueries(
resourceType: Resource::TYPE_TEAM,
resourceIds: $resourceIds,
cursor: $lastTeam
);
$teamList = $this->teams->list($params);

$totalTeams = $teamList['total'];
Expand All @@ -244,13 +246,18 @@ private function reportAuth(array $resources, array &$report): void
$allTeams = array_merge($allTeams, $currentTeams);
$lastTeam = $currentTeams[count($currentTeams) - 1]['$id'] ?? null;

if (count($currentTeams) < $pageLimit) {
if (count($currentTeams) < self::DEFAULT_PAGE_LIMIT) {
break;
}
}
$teams = ['total' => $totalTeams, 'teams' => $allTeams];
} else {
$teamList = $this->teams->list([Query::limit(1)]);
$params = $this->buildQueries(
resourceType: Resource::TYPE_TEAM,
resourceIds: $resourceIds,
limit: 1
);
$teamList = $this->teams->list($params);
$teams = ['total' => $teamList['total'], 'teams' => []];
}
}
Expand All @@ -274,56 +281,62 @@ private function reportAuth(array $resources, array &$report): void
* @throws Exception
* @throws AppwriteException
*/
private function reportDatabases(array $resources, array &$report): void
private function reportDatabases(array $resources, array &$report, array $resourceIds = []): void
{
$this->database->report($resources, $report);
$this->database->report($resources, $report, $resourceIds);
}

/**
* @param array $resources
* @param array $report
* @param array<string, array<string>> $resourceIds
* @throws AppwriteException
*/
private function reportStorage(array $resources, array &$report): void
private function reportStorage(array $resources, array &$report, array $resourceIds = []): void
{

if (\in_array(Resource::TYPE_BUCKET, $resources)) {
// just fetch one bucket for the `total`
$report[Resource::TYPE_BUCKET] = $this->storage->listBuckets([
Query::limit(1)
])['total'];
$bucketQueries = $this->buildQueries(
resourceType: Resource::TYPE_BUCKET,
resourceIds: $resourceIds,
limit: 1
);
$report[Resource::TYPE_BUCKET] = $this->storage->listBuckets($bucketQueries)['total'];
}

$pageLimit = 25;

if (\in_array(Resource::TYPE_FILE, $resources)) {
$report[Resource::TYPE_FILE] = 0;
$report['size'] = 0;
$buckets = [];
$lastBucket = null;

while (true) {
$currentBuckets = $this->storage->listBuckets(
$lastBucket
? [Query::cursorAfter($lastBucket)]
: [Query::limit($pageLimit)]
)['buckets'];
$queries = $this->buildQueries(
resourceType: Resource::TYPE_BUCKET,
resourceIds: $resourceIds,
cursor: $lastBucket,
);
$currentBuckets = $this->storage->listBuckets($queries)['buckets'];

$buckets = array_merge($buckets, $currentBuckets);
$lastBucket = $buckets[count($buckets) - 1]['$id'] ?? null;

if (count($currentBuckets) < $pageLimit) {
if (count($currentBuckets) < self::DEFAULT_PAGE_LIMIT) {
break;
}
}

foreach ($buckets as $bucket) {
$lastFile = null;
while (true) {
$queries = [Query::limit(self::DEFAULT_PAGE_LIMIT)];
if ($lastFile) {
$queries[] = Query::cursorAfter($lastFile);
}

$files = $this->storage->listFiles(
$bucket['$id'],
$lastFile
? [Query::cursorAfter($lastFile)]
: [Query::limit($pageLimit)]
$queries
)['files'];

$report[Resource::TYPE_FILE] += count($files);
Expand All @@ -334,7 +347,7 @@ private function reportStorage(array $resources, array &$report): void

$lastFile = $files[count($files) - 1]['$id'] ?? null;

if (count($files) < $pageLimit) {
if (count($files) < self::DEFAULT_PAGE_LIMIT) {
break;
}
}
Expand All @@ -344,9 +357,8 @@ private function reportStorage(array $resources, array &$report): void
}
}

private function reportFunctions(array $resources, array &$report): void
private function reportFunctions(array $resources, array &$report, array $resourceIds = []): void
{
$pageLimit = 25;
$needVarsOrDeployments = (
\in_array(Resource::TYPE_DEPLOYMENT, $resources) ||
\in_array(Resource::TYPE_ENVIRONMENT_VARIABLE, $resources)
Expand All @@ -356,27 +368,31 @@ private function reportFunctions(array $resources, array &$report): void
$totalFunctions = 0;

if (!$needVarsOrDeployments && \in_array(Resource::TYPE_FUNCTION, $resources)) {
// Only function count needed, short-circuit
$funcList = $this->functions->list([Query::limit(1)]);
$report[Resource::TYPE_FUNCTION] = $funcList['total'];
$functionQueries = $this->buildQueries(
resourceType: Resource::TYPE_FUNCTION,
resourceIds: $resourceIds,
limit: 1
);
$report[Resource::TYPE_FUNCTION] = $this->functions->list($functionQueries)['total'];
return;
}

if ($needVarsOrDeployments) {
$lastFunction = null;
while (true) {
$params = $lastFunction
? [Query::cursorAfter($lastFunction)]
: [Query::limit($pageLimit)];

$params = $this->buildQueries(
resourceType: Resource::TYPE_FUNCTION,
resourceIds: $resourceIds,
cursor: $lastFunction,
);
$funcList = $this->functions->list($params);

$totalFunctions = $funcList['total'];
$currentFunctions = $funcList['functions'];
$functions = array_merge($functions, $currentFunctions);

$lastFunction = $currentFunctions[count($currentFunctions) - 1]['$id'] ?? null;
if (count($currentFunctions) < $pageLimit) {
if (count($currentFunctions) < self::DEFAULT_PAGE_LIMIT) {
break;
}
}
Expand Down Expand Up @@ -1614,4 +1630,30 @@ private function exportDeploymentData(Func $func, array $deployment): void
}
}
}

/**
* Build queries with optional filtering by resource IDs
*/
private function buildQueries(
string $resourceType,
array $resourceIds,
?string $cursor = null,
int $limit = self::DEFAULT_PAGE_LIMIT
): array {
$queries = [];

if (!empty($resourceIds[$resourceType])) {
$ids = (array) $resourceIds[$resourceType];

$queries[] = Query::equal('$id', $ids);
}

if ($cursor) {
$queries[] = Query::cursorAfter($cursor);
} else {
$queries[] = Query::limit($limit);
}

return $queries;
}
}
3 changes: 2 additions & 1 deletion src/Migration/Sources/Appwrite/Reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ interface Reader
*
* @param array $resources
* @param array $report
* @param array<string, array<string>> $resourceIds
* @return mixed
*/
public function report(array $resources, array &$report): mixed;
public function report(array $resources, array &$report, array $resourceIds = []): mixed;

/**
* List databases that match the given queries
Expand Down
11 changes: 9 additions & 2 deletions src/Migration/Sources/Appwrite/Reader/API.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function __construct(
/**
* @throws AppwriteException
*/
public function report(array $resources, array &$report): mixed
public function report(array $resources, array &$report, array $resourceIds = []): mixed
{
$relevantResources = [
Resource::TYPE_DATABASE,
Expand All @@ -45,7 +45,14 @@ public function report(array $resources, array &$report): mixed
}
}

$databasesResponse = $this->database->list();
$databaseQueries = [];
if (!empty($resourceIds[Resource::TYPE_DATABASE])) {
$databaseIds = (array) $resourceIds[Resource::TYPE_DATABASE];

$databaseQueries[] = Query::equal('$id', $databaseIds);
}

$databasesResponse = $this->database->list($databaseQueries);
$databases = $databasesResponse['databases'];

if (in_array(Resource::TYPE_DATABASE, $resources)) {
Expand Down
14 changes: 10 additions & 4 deletions src/Migration/Sources/Appwrite/Reader/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function __construct(private readonly UtopiaDatabase $dbForProject)
{
}

public function report(array $resources, array &$report): mixed
public function report(array $resources, array &$report, array $resourceIds = []): mixed
{
$relevantResources = [
Resource::TYPE_DATABASE,
Expand All @@ -44,8 +44,15 @@ public function report(array $resources, array &$report): mixed
}
}

$databaseQueries = [];
if (!empty($resourceIds[Resource::TYPE_DATABASE])) {
$databaseIds = (array) $resourceIds[Resource::TYPE_DATABASE];

$databaseQueries[] = Query::equal('$id', $databaseIds);
}

if (in_array(Resource::TYPE_DATABASE, $resources)) {
$report[Resource::TYPE_DATABASE] = $this->countResources('databases');
$report[Resource::TYPE_DATABASE] = $this->countResources('databases', $databaseQueries);
}

if (count(array_intersect($resources, $relevantResources)) === 1 &&
Expand All @@ -54,7 +61,7 @@ public function report(array $resources, array &$report): mixed
}

$dbResources = [];
$databases = $this->listDatabases();
$databases = $this->listDatabases($databaseQueries);

// Process each database
foreach ($databases as $database) {
Expand Down Expand Up @@ -417,7 +424,6 @@ public function queryLimit(int $limit): Query
* @param string $table
* @param array $queries
* @return int
* @throws DatabaseException
*/
private function countResources(string $table, array $queries = []): int
{
Expand Down
Loading