Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement global position #169

Open
johanhaleby opened this issue Nov 15, 2024 · 1 comment
Open

Implement global position #169

johanhaleby opened this issue Nov 15, 2024 · 1 comment

Comments

@johanhaleby
Copy link
Owner

johanhaleby commented Nov 15, 2024

Use snowflake-id and generate the id like this:

import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.Random;

public class NodeIdGenerator {

    private static final int MAX_NODE_ID = 1024; // 10-bit node ID space

    /**
     * Generate a unique node ID by combining current time in millis and a unique machine fingerprint.
     * Falls back to random salt if MAC address is unavailable.
     */
    public static int generateNodeId() {
        long epochMillis = System.currentTimeMillis();
        String machineFingerprint = getMachineFingerprint();
        if (machineFingerprint == null) {
            machineFingerprint = generateRandomSalt();
        }

        // Combine epochMillis and machine fingerprint to generate a unique ID
        String uniqueString = epochMillis + "-" + machineFingerprint;
        return hashToInt(uniqueString, MAX_NODE_ID);
    }

    /**
     * Get the MAC address as a unique identifier.
     */
    private static String getMachineFingerprint() {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface network = networkInterfaces.nextElement();
                byte[] mac = network.getHardwareAddress();

                if (mac != null) {
                    StringBuilder macAddress = new StringBuilder();
                    for (byte b : mac) {
                        macAddress.append(String.format("%02X", b));
                    }
                    return macAddress.toString();
                }
            }
        } catch (Exception e) {
            // Fallback if MAC address cannot be determined
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Generate a random salt for cases where MAC address is unavailable.
     */
    private static String generateRandomSalt() {
        Random random = new Random();
        byte[] salt = new byte[6]; // Generate 6 random bytes
        random.nextBytes(salt);

        StringBuilder saltString = new StringBuilder();
        for (byte b : salt) {
            saltString.append(String.format("%02X", b));
        }
        return saltString.toString();
    }

    /**
     * Hash the input string to an integer and constrain it to the max value.
     */
    private static int hashToInt(String input, int maxValue) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes());

            // Use the first 4 bytes of the hash to compute an integer
            int result = 0;
            for (int i = 0; i < 4; i++) {
                result = (result << 8) | (hash[i] & 0xFF);
            }
            return Math.abs(result) % maxValue;
        } catch (Exception e) {
            throw new RuntimeException("Error hashing input string", e);
        }
    }

    public static void main(String[] args) {
        int nodeId = generateNodeId();
        System.out.println("Generated Node ID: " + nodeId);
    }
}
@johanhaleby
Copy link
Owner Author

johanhaleby commented Nov 15, 2024

For backward compatibility: just use "time" converted to epoch millis as sequenceNumber, maybe combine it with properties of the "_id" field if epoch millis clash.

@johanhaleby johanhaleby changed the title Implement global sequence number Implement global position Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant