Page MenuHomePhabricator

Add unique constraint to AlmanacInterfaces
ClosedPublic

Authored by amckinley on Apr 19 2018, 10:47 PM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Apr 19, 7:42 PM
Unknown Object (File)
Thu, Apr 18, 5:15 AM
Unknown Object (File)
Wed, Apr 17, 4:06 PM
Unknown Object (File)
Tue, Apr 16, 1:41 AM
Unknown Object (File)
Mon, Apr 15, 6:07 PM
Unknown Object (File)
Mon, Apr 15, 6:07 PM
Unknown Object (File)
Thu, Apr 11, 11:31 PM
Unknown Object (File)
Thu, Apr 11, 11:31 PM
Subscribers
Restricted Owners Package

Details

Summary

See discussion in D19379. The 4-tuple of (device, network, address, port) should be unique.

Test Plan

Created lots of duplicate interfaces, bound those interfaces to various services, observed migration script clean things up correctly.

Diff Detail

Repository
rP Phabricator
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

Owners added a subscriber: Restricted Owners Package.Apr 19 2018, 10:47 PM
resources/sql/autopatches/20180418.alamanc.interface.unique.php
28–31

This currently doesn't work if I acquire the LOCK at the beginning of the script. Do I need to be using queryfx() exclusively? See error here: P2098

I haven't run into that LOCK TABLE thing before, but some googling suggests that maybe you need to be using raw queryfx() stuff on the same $conn? I'd normally expect the existing w mode $conn to get reused (since we can use a 'w' conn for 'r'), but maybe that isn't actually what happens today.

Using $binding->save() is dangerous anyway because if any future version of Phabricator ever adds a column to AlmanacBinding, the code will stop working. The safe version of this is just to update the table directly, anyway.

So the intermediate query logic should probably just be queryfx(...) stuff for that reason, which will probably fix the LOCK TABLE issue as a side effect?

I'd also probably just directly DELETE the rows being removed for similar reasons -- DestructionEngine has a lot of logging side effects which may break as the codebase moves forward.

I think we'll be left with a semi-weird possible edge case where maybe some stray binding properties get left over if your data was super weird, but we can just live with that.

This change looks right to me structurally.

Okie dokie. I was also wondering if I need to create any transaction objects for reattaching the bindings, but I doubt that will work if I'm restricted to queryfx.

Definitely OK to just make the rows as-correct-as-possible without writing transactions for them.

switch to using queryfx() everywhere, add didCatchDuplicateKeyException() hook

I think this reattaches the bindings to the interface we delete, not the actual survivor? Maybe I'm crazy but:

  • The first interface (say, ID 1) gets marked as $seen.
  • The second interface (say, ID 2) actually goes into the logic.
  • But we select the SECOND interface (ID 2) as the "$survivor", rebind to it, and then delete it? I think? We should actually be selecting $seen[$key] (ID 1) as the survivor, I think?

This otherwise looks right to me. Not sure if I'm misreading that / missing something. I can try it locally and give you more specific repro instructions if that sounds crazy.

Whoops, good catch, you're right. I copy/pasted incorrectly when migrating to queryfx.

Macro bythepowerof: BY THE POWER OF CODE REVIEW

I can't come up with any other ways to break this.

This revision is now accepted and ready to land.Apr 20 2018, 1:56 AM
This revision was automatically updated to reflect the committed changes.