package synchronizator import ( "context" sql "database/sql" "fmt" "slices" ) type platform_has_collection struct { Relationship } func (col_has_node *platform_has_collection) GetClass() string { return "PLATFORM_HAS_COLLECTION" } func (col_has_node *platform_has_collection) GetMetadata() []byte { return nil } func (col_has_node *platform_has_collection) FromRelationship( _class string, metadata []byte, ) error { if _class != "PLATFORM_HAS_COLLECTION" { return fmt.Errorf("invalid class %s", _class) } return nil } // Platform represents a collection of nodes. It embeds a Node, so all the // node's functionality is available. type Platform struct { Node // Underlying node info Collections []*Collection // Child nodes } func (platform *Platform) AddCollection( name string, metadata, originalData []byte, ) (*Collection, error) { var collection *Collection err := platform._conn.withTx(func(tx *sql.Tx) error { node, err := platform._conn.newCollectionwithTx(tx, name, metadata, originalData) if err != nil { return err } _, err = platform._conn.addRelationwithTx( tx, platform.Id, &platform_has_collection{}, node.Id, ) if err != nil { return err } collection = node return nil }) if err != nil { return nil, err } platform.Collections = append(platform.Collections, collection) return collection, nil } func (platform *Platform) loadCollections() error { sql := ` WITH RECURSIVE NodeRelationships AS ( SELECT *, relationships._class AS relationship_class, relationships.metadata AS relationship_metadata FROM nodes as src JOIN relationships ON src.id = relationships.node_from WHERE src.id = $1 AND relationships._class = 'PLATFORM_HAS_COLLECTION' ) SELECT dst.id, dst.name, dst._class, dst.metadata, dst.original_data FROM NodeRelationships JOIN nodes as dst ON dst.id = NodeRelationships.node_to ` rows, err := platform._conn.Query(sql, platform.Id) if err != nil { return err } defer rows.Close() platform._relationships = make([]StandardRelationship, 0) platform.Collections = make([]*Collection, 0) for rows.Next() { collection := &Collection{ Node: Node{ _conn: platform._conn, }, } if err := rows.Scan( &collection.Id, &collection.name, &collection._class, &collection.metadata, &collection.originalData, ); err != nil { return err } platform.Collections = append(platform.Collections, collection) } return nil } func (platform *Platform) GetDefaultCollection() (*Collection, error) { for _, collection := range platform.Collections { if collection.IsDefault() { return collection, nil } } return nil, fmt.Errorf("Default collection not found") } // Is a type alias for FetchResponse containing a slice of Collection pointers. type FetchCollectionResponse = FetchResponse[[]*Collection] // Fetches collections using the provided fetcher and pagination settings. // It updates the platform's collections and creates relationships between the platform and the collections. // // Parameters: // - ctx: The context to control cancellation. // - fetcher: The fetcher function to execute the work. // - start_pagination: The initial pagination settings. // - pool_config: The configuration for the worker pool. // // Returns: // - error: The error if any occurred. func (platform *Platform) FetchCollections( ctx context.Context, fetcher Work[Pagination, FetchCollectionResponse], startPagination Pagination, poolConfig *WorkConfig, ) error { values, err := fetchWithPagination(ctx, poolConfig, fetcher, startPagination) if err != nil { return err } platform.Collections = slices.Concat(platform.Collections, values) fmt.Printf("Collections: %v\n", len(platform.Collections)) err = BulkCreateNode(platform._conn, values) if err != nil { return err } relationships := make([]*Relationship, 0, len(values)) for _, item := range values { relation := &Relationship{ _class: "PLATFORM_HAS_COLLECTION", From: platform.Id, To: item.Id, } err := platform.AddRelationship(relation) if err != nil { return err } relationships = append(relationships, relation) } err = BulkCreateRelationships(platform._conn, relationships) if err != nil { return err } return nil }