2

Is it a good practise to keep the table generation in your production code?

I'm referring too:

Await.ready(database.autocreate().future(), 2 minutes)

Are there any potential issues with leaving this in? Just looking for some explanation on if it is a good idea or not.

Is it better to keep this type of work outside in some sort of a script to run during initial rollout and migrations?

cool breeze
  • 4,461
  • 5
  • 38
  • 67

3 Answers3

1

I fully and very strongly disagree with all the advice given above. The whole point of phantom is to never have to write CQL, and we have complete mechanisms that allow you to control how your schema gets initialised, inclusive of all possible properties.

Have a look at the tests here or at the default Cassandra initialisation, there's pretty much nothing you can't do.

Custom settings in autocreation

If you want to provide all those params instead of defaults during database.autocreate, that's really simple too:

class MyTable extends CassandraTable[MyTable, MyRecord] {
 override def autocreate(
  keySpace: KeySpace
 ): CreateQuery.Default[T, R] = create.ifNotExists()(keySpace)
   .`with`(compaction eqs LeveledCompactionStrategy.sstable_size_in_mb(50))
   .and(compression eqs LZ4Compressor.crc_check_chance(0.5))
}

Later when you do this:

class MyDB(override val connector: KeySpaceDef) extends Database {
  object myTable extends MyTable with connector.Connector
}

And you do:

   val database = new MyDB(ContactPoint.local.keySpace("whatever")

When you run database.createAsync or database.create, all the settings you defined above will be respected.

Custom keyspace autocreation

Phantom also supports specifying custom keyspace initialisation queries during keyspace autogeneration.

val init = KeySpaceSerializer("my_app").ifNotExists()
    .`with`(replication eqs SimpleStrategy.replication_factor(2))
    .and(durable_writes eqs true)

val connector = ContactPoint.local.keySpace(
  "my_app",
  (session, space): (Session, KeySpace) => init.queryString
 )

This way you can benefit from any known form of customisation you can think of while still not having to deal with CQL. If you use phantom-pro which will shortly be available for subscription, there will also be automated schema migration capability, so holding your schema in any kind of CQL is a very big no no.

Phantom also transparently handles CQL variations between versions, I've never seen a bash script who does that, so you can get into unpleasantries quite quickly with a simple Cassandra upgrade/downgrade, and why would you if you can just automate things?

flavian
  • 28,161
  • 11
  • 65
  • 105
  • I'm not saying to not use phantom, but should this autocreate be inside of our persistence layer that gets called each time the jvm process runs? – cool breeze Oct 26 '16 at 15:36
  • @coolbreeze By default the query uses `ifNotExists`, so the entire thing is idempotent and it won't override any settings. A few calls to Cassandra won't really do anything to your overall performance, you won't even feel they exist really. Phantom 2.0.0 that will be available shortly is even a lot faster as we have dropped reflection. – flavian Oct 26 '16 at 15:47
  • I think it's more a personal opinion. My team decided to do not use any table customisation and initialisation inside the code, so I see nothing wrong with this approach as well. – Thiago Pereira Oct 31 '16 at 10:30
  • @flavian Is the database autocreate supposed to create tables in Phantom 2.7.6? I have added myDatabase.create(/* timeout */)(/* executor */), but this only seems to create the keyspace. I have one table so far. Thanks. [edit] Also, adding `autocreate` to the table class (abstract class MyClass extends CassandraTable[MyClass, Int] with RootConnector) body doesn't seem to do anything either - it doesn't create the table. – Sandro Gržičić May 15 '17 at 14:19
  • 1
    https://github.com/outworkers/phantom/blob/develop/docs/basics/database.md – flavian May 15 '17 at 14:21
  • Thank you, I will try that. There's a lot of conflicting documentation available. EDIT `create.ifNotExists()` within the table class body didn't create the table. I will try it outside. – Sandro Gržičić May 15 '17 at 14:25
  • `create.ifNotExists()` seemed to work when called outside the table definition, after the table class is instantiated. I can see my table now. However I would prefer if I could call the method from inside the class - how come that is not possible? – Sandro Gržičić May 15 '17 at 14:41
  • 1
    You can read the docs, call the method from wherever you like. – flavian May 15 '17 at 15:04
-1

The table creation/modification logic may not be useful once after installation or upgrade. Further, it may not be safe/not required to keep it in the production code. So, keep your code/scripts at bootstrap or installer level.

Kris
  • 1,618
  • 1
  • 13
  • 13
-1

As already pointed out, from my experience this is not something you would like to have. I have been using phantom in production for more than a year, and the only place I left the table creation to be something automatically, was inside my tests, running with an embedded version.

You can find out more here: https://github.com/iamthiago/cassandra-phantom/blob/master/src/test/scala/com/cassandra/phantom/modeling/test/service/SongsTest.scala

To push it further, there is a similar discussion with hibernate. You can take a look here: Hibernate/JPA DB Schema Generation Best Practices

Thiago Pereira
  • 1,724
  • 1
  • 17
  • 31