def upsert_rpsl_object(self, rpsl_object: RPSLObject, forced_serial: Optional[int] = None) -> None: """ Schedule an RPSLObject for insertion/updating. This method will insert the object, or overwrite an existing object if it has the same RPSL primary key and source. No other checks are applied before overwriting. Writes may not be issued to the database immediately for performance reasons, but commit() will ensure all writes are flushed to the DB first. The forced serial is needed for mirrored sources, where this basically means: this call was triggered by an NRTM operation with this serial. """ ip_first = str(rpsl_object.ip_first) if rpsl_object.ip_first else None ip_last = str(rpsl_object.ip_last) if rpsl_object.ip_last else None ip_size = None if rpsl_object.ip_first and rpsl_object.ip_last: ip_size = rpsl_object.ip_last.int() - rpsl_object.ip_first.int( ) + 1 # In some cases, multiple updates may be submitted for the same object. # PostgreSQL will not allow rows proposed for insertion to have duplicate # constrained values - so if a second object appears with a pk/source # seen before, the cache must be flushed right away, or the two updates # will conflict. source = rpsl_object.parsed_data['source'] rpsl_pk_source = rpsl_object.pk() + '-' + source if rpsl_pk_source in self._rpsl_pk_source_seen: self._flush_rpsl_object_upsert_cache() self._rpsl_upsert_cache.append(( { 'rpsl_pk': rpsl_object.pk(), 'source': source, 'object_class': rpsl_object.rpsl_object_class, 'parsed_data': rpsl_object.parsed_data, 'object_text': rpsl_object.render_rpsl_text(), 'ip_version': rpsl_object.ip_version(), 'ip_first': ip_first, 'ip_last': ip_last, 'ip_size': ip_size, 'asn_first': rpsl_object.asn_first, 'asn_last': rpsl_object.asn_last, 'updated': datetime.now(timezone.utc), }, forced_serial, )) self._rpsl_pk_source_seen.add(rpsl_pk_source) self._object_classes_modified.add(rpsl_object.rpsl_object_class) if len(self._rpsl_upsert_cache) > MAX_RECORDS_CACHE_BEFORE_INSERT: self._flush_rpsl_object_upsert_cache()
def upsert_rpsl_object(self, rpsl_object: RPSLObject, origin: JournalEntryOrigin, rpsl_guaranteed_no_existing=False, source_serial: Optional[int] = None, forced_created_value: Optional[str] = None) -> None: """ Schedule an RPSLObject for insertion/updating. This method will insert the object, or overwrite an existing object if it has the same RPSL primary key and source. No other checks are applied before overwriting. Writes may not be issued to the database immediately for performance reasons, but commit() will ensure all writes are flushed to the DB first. The origin indicates the origin of this change, see JournalEntryOrigin for the various options. The source_serial is the serial that an NRTM source assigned to this change, if any. If rpsl_guaranteed_no_existing is set to True, the caller guarantees that this PK is unique in the database. This essentially only applies to inserting RPKI psuedo-IRR objects. """ self._check_write_permitted() if not rpsl_guaranteed_no_existing: self._rpsl_guaranteed_no_existing = False ip_first = str(rpsl_object.ip_first) if rpsl_object.ip_first else None ip_last = str(rpsl_object.ip_last) if rpsl_object.ip_last else None ip_size = None if rpsl_object.ip_first and rpsl_object.ip_last: ip_size = rpsl_object.ip_last.int() - rpsl_object.ip_first.int( ) + 1 # In some cases, multiple updates may be submitted for the same object. # PostgreSQL will not allow rows proposed for insertion to have duplicate # constrained values - so if a second object appears with a pk/source # seen before, the buffer must be flushed right away, or the two updates # will conflict. source = rpsl_object.parsed_data['source'] rpsl_pk_source = rpsl_object.pk() + '-' + source if rpsl_pk_source in self._rpsl_pk_source_seen: self._flush_rpsl_object_writing_buffer() update_time = datetime.now(timezone.utc) object_dict = { 'rpsl_pk': rpsl_object.pk(), 'source': source, 'object_class': rpsl_object.rpsl_object_class, 'parsed_data': rpsl_object.parsed_data, 'object_text': rpsl_object.render_rpsl_text(last_modified=update_time), 'ip_version': rpsl_object.ip_version(), 'ip_first': ip_first, 'ip_last': ip_last, 'ip_size': ip_size, 'prefix': str(rpsl_object.prefix) if rpsl_object.prefix else None, 'prefix_length': rpsl_object.prefix_length, 'asn_first': rpsl_object.asn_first, 'asn_last': rpsl_object.asn_last, 'rpki_status': rpsl_object.rpki_status, 'scopefilter_status': rpsl_object.scopefilter_status, 'updated': update_time, } if forced_created_value: object_dict['created'] = forced_created_value self._rpsl_upsert_buffer.append((object_dict, origin, source_serial)) self._rpsl_pk_source_seen.add(rpsl_pk_source) self._object_classes_modified.add(rpsl_object.rpsl_object_class) if len(self._rpsl_upsert_buffer) > MAX_RECORDS_BUFFER_BEFORE_INSERT: self._flush_rpsl_object_writing_buffer()