Class: Namespace::TraversalHierarchy

Inherits:
Object
  • Object
show all
Includes:
Transactions
Defined in:
app/models/namespace/traversal_hierarchy.rb

Constant Summary collapse

LOCK_TIMEOUT =
'1000ms'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root) ⇒ TraversalHierarchy

Returns a new instance of TraversalHierarchy.

Raises:

  • (StandardError)


22
23
24
25
26
# File 'app/models/namespace/traversal_hierarchy.rb', line 22

def initialize(root)
  raise StandardError, 'Must specify a root node' if root.parent_id

  @root = root
end

Instance Attribute Details

#rootObject

Returns the value of attribute root.



20
21
22
# File 'app/models/namespace/traversal_hierarchy.rb', line 20

def root
  @root
end

Class Method Details

.for_namespace(namespace) ⇒ Object



41
42
43
# File 'app/models/namespace/traversal_hierarchy.rb', line 41

def for_namespace(namespace)
  new(recursive_root_ancestor(namespace))
end

.recursive_traversal_ids(node) ⇒ Object

Determine traversal_ids for the node and it’s descendants using recursive methods. Generate a collection of [id, traversal_ids] rows.

Note that the traversal_ids represent a calculated traversal path for the namespace and not the value stored within the traversal_ids attribute. rubocop:disable Cop/AvoidBecomes – Normalize STI queries



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/namespace/traversal_hierarchy.rb', line 59

def recursive_traversal_ids(node)
  node_id = Integer(node.id)
  ancestor_ids = if node.parent_id
                   node
                     .becomes(Namespace)
                     .recursive_self_and_ancestor_ids
                     .reverse
                     .join(',')
                 else
                   node_id
                 end

  "  WITH RECURSIVE cte(id, traversal_ids, cycle) AS (\n    VALUES(\#{node_id}::bigint, ARRAY[\#{ancestor_ids}]::bigint[], false)\n  UNION ALL\n    SELECT n.id, cte.traversal_ids || n.id::bigint, n.id = ANY(cte.traversal_ids)\n    FROM namespaces n, cte\n    WHERE n.parent_id = cte.id AND NOT cycle\n  )\n  SELECT id, traversal_ids FROM cte\n  SQL\nend\n"

.sync_traversal_ids!(node) ⇒ Object

Update all traversal_ids for the given namespace and it’s descendants.



46
47
48
49
50
51
# File 'app/models/namespace/traversal_hierarchy.rb', line 46

def sync_traversal_ids!(node)
  Namespace.transaction do
    acquire_locks(node)
    sync_traversal_ids_tree!(node)
  end
end

Instance Method Details

#incorrect_traversal_idsObject

Identify all incorrect traversal_ids in the current namespace hierarchy.



34
35
36
37
38
# File 'app/models/namespace/traversal_hierarchy.rb', line 34

def incorrect_traversal_ids
  Namespace
    .joins("INNER JOIN (#{TraversalHierarchy.recursive_traversal_ids(root)}) as cte ON namespaces.id = cte.id")
    .where('namespaces.traversal_ids::bigint[] <> cte.traversal_ids')
end

#sync_traversal_ids!Object

Update all traversal_ids in the current namespace hierarchy.



29
30
31
# File 'app/models/namespace/traversal_hierarchy.rb', line 29

def sync_traversal_ids!
  TraversalHierarchy.sync_traversal_ids!(root)
end